agent-inspect 6.17.4 → 6.17.5
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 +6 -0
- package/README.md +1 -1
- package/docs/ADAPTERS.md +3 -3
- package/docs/API.md +13 -7
- package/docs/CLI.md +2 -0
- package/docs/LIMITATIONS.md +1 -0
- package/docs/TRACE-CONTRACTS.md +90 -0
- package/package.json +5 -2
- package/packages/cli/dist/{chunk-YX6RFLV5.mjs → chunk-GOHYSE7W.mjs} +86 -17
- package/packages/cli/dist/chunk-GOHYSE7W.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +480 -80
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +399 -68
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-X6SLMBNH.mjs → src-OYGG7QAZ.mjs} +3 -3
- package/packages/cli/dist/{src-X6SLMBNH.mjs.map → src-OYGG7QAZ.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +85 -16
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +1 -1
- package/packages/core/dist/advanced.d.ts +1 -1
- package/packages/core/dist/advanced.mjs +15 -5
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +119 -26
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.d.cts +28 -2
- package/packages/core/dist/checks.d.ts +28 -2
- package/packages/core/dist/checks.mjs +1 -1
- package/packages/core/dist/{chunk-HN377P23.mjs → chunk-DIZPIPY2.mjs} +121 -28
- package/packages/core/dist/chunk-DIZPIPY2.mjs.map +1 -0
- package/packages/core/dist/{index-Xk9X-yjY.d.cts → index-DWu54Y28.d.cts} +107 -122
- package/packages/core/dist/{index-BsCcOKxy.d.ts → index-DlwbVqEs.d.ts} +107 -122
- package/packages/cli/dist/chunk-YX6RFLV5.mjs.map +0 -1
- package/packages/core/dist/chunk-HN377P23.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.17.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 093811b: Harden deterministic TraceContract / check gates against fail-open empty configs (rule execution evidence, unique order IDs, requiredOrder implies presence, tool policy includes running invocations, ObservedOutcome requireAny), map #308–#311 release ownership, and make demo:verify / pack:smoke validation cross-platform without unnecessary shell invocation.
|
|
8
|
+
|
|
3
9
|
## 6.17.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -210,7 +210,7 @@ The root package is enough for custom capture, the CLI, checks, and Evidence wor
|
|
|
210
210
|
|
|
211
211
|
## Status and documentation
|
|
212
212
|
|
|
213
|
-
**Current published baseline:** **6.17.
|
|
213
|
+
**Current published baseline:** **6.17.5** · persisted schema `1.0` · Node.js `>=20` · MIT.
|
|
214
214
|
|
|
215
215
|
Legacy v0.1 and v0.2 traces remain readable. Check the npm badge and [changelog](CHANGELOG.md) for the current published version.
|
|
216
216
|
|
package/docs/ADAPTERS.md
CHANGED
|
@@ -22,7 +22,7 @@ Reporters (`@agent-inspect/vitest` and `@agent-inspect/jest`) are public package
|
|
|
22
22
|
|
|
23
23
|
**Status:** experimental adapter — optional package published in the aligned v2.2.0 package set and hardened in the v2.3 adapter train.
|
|
24
24
|
|
|
25
|
-
The adapter has hardened lifecycle identity and parallel integration isolation. It remains metadata-only: `capture: "preview"` and preview-only redaction options emit diagnostics and fall back to metadata-only capture
|
|
25
|
+
The adapter has hardened lifecycle identity and parallel integration isolation. It remains metadata-only: `capture: "preview"` and preview-only redaction options emit diagnostics **and one visible** `AI_ADAPTER_PREVIEW_NOT_AVAILABLE` warning per adapter instance, then fall back to metadata-only capture. Bounded free-text preview capture is planned for a later train; it is not implemented here.
|
|
26
26
|
|
|
27
27
|
### Install
|
|
28
28
|
|
|
@@ -59,7 +59,7 @@ const result = await generateText({
|
|
|
59
59
|
- **Metadata-only by default** — records model, finish reason, token usage, timing, and safe counts/summaries.
|
|
60
60
|
- **Required safe telemetry settings** — set `recordInputs: false` and `recordOutputs: false` on every AI SDK call using this adapter.
|
|
61
61
|
- **No raw payload capture by default** — prompts, messages, generated text, stream chunks, tool inputs/outputs, headers, request bodies, and response bodies are not persisted.
|
|
62
|
-
- **Preview capture is not enabled yet** — `capture: "preview"
|
|
62
|
+
- **Preview capture is not enabled yet** — requesting `capture: "preview"` emits one console warning with code `AI_ADAPTER_PREVIEW_NOT_AVAILABLE`, records diagnostics via `getDiagnostics()`, and does not persist raw previews. Effective capture remains metadata-only.
|
|
63
63
|
|
|
64
64
|
### Local no-network recipe
|
|
65
65
|
|
|
@@ -375,7 +375,7 @@ Integration modes:
|
|
|
375
375
|
- **No upload behavior** — the processor writes only to an explicit local writer or `traceDir`.
|
|
376
376
|
- **Metadata-only by default** — records trace/span IDs, parentage, names, timing, status, errors, safe model/tool names, token counts, and bounded summaries.
|
|
377
377
|
- **No raw payload capture by default** — prompts, messages, generated text, function inputs/outputs, arbitrary custom data, trace exporter credentials, headers, request bodies, response bodies, and hosted tool payloads are not persisted.
|
|
378
|
-
- **Preview capture is not enabled yet** — `capture: "preview"
|
|
378
|
+
- **Preview capture is not enabled yet** — requesting `capture: "preview"` emits one console warning with code `AI_ADAPTER_PREVIEW_NOT_AVAILABLE`, records diagnostics via `getDiagnostics()`, and does not persist raw previews. Effective capture remains metadata-only.
|
|
379
379
|
- **Fixture-backed lifecycle coverage** — local tests and the recipe cover agent, generation, function tool, handoff, guardrail, response, MCP tools, custom, transcription, and speech span shapes without provider calls.
|
|
380
380
|
|
|
381
381
|
Full API: [API.md](./API.md) §14.
|
package/docs/API.md
CHANGED
|
@@ -180,7 +180,11 @@ Diff is local and read-only. Programmatic diff surfaces are experimental until t
|
|
|
180
180
|
- In-memory **`getEvents()`** / **`clear()`** unchanged when `persist` is false
|
|
181
181
|
- Metadata helpers: `extractModelName`, `extractTokenUsage`, `safePreview`, `toPlainMetadata`
|
|
182
182
|
|
|
183
|
-
Rationale:
|
|
183
|
+
Rationale: one official adapter and **zero production sinks** keep adapter surfaces experimental; they remain additive in minors.
|
|
184
|
+
|
|
185
|
+
### TraceContract `requiredOrder`
|
|
186
|
+
|
|
187
|
+
When defining `tools.requiredOrder`, the array expands into adjacent first-occurrence pair checks. Unlisted intermediate tools are allowed; later repetitions do not invalidate an earlier valid first-occurrence order. Missing tools are handled by required-tool rules, not ordering alone. See [TRACE-CONTRACTS.md](./TRACE-CONTRACTS.md).
|
|
184
188
|
|
|
185
189
|
## 10. Experimental `@agent-inspect/tui` APIs
|
|
186
190
|
|
|
@@ -249,7 +253,7 @@ The manifest records framework, generation time, bounded test results, artifact
|
|
|
249
253
|
|
|
250
254
|
## 12. Experimental `@agent-inspect/vitest` APIs
|
|
251
255
|
|
|
252
|
-
`@agent-inspect/vitest` is an optional experimental workspace package for local Vitest failure artifacts. It
|
|
256
|
+
`@agent-inspect/vitest` is an optional experimental workspace package for local Vitest failure artifacts. It is published with the fixed release group. It does not add a Vitest dependency to root/core, does not upload artifacts, and does not infer trace relationships by timestamp.
|
|
253
257
|
|
|
254
258
|
Import from `@agent-inspect/vitest`:
|
|
255
259
|
|
|
@@ -282,7 +286,7 @@ Artifacts are safe structural summaries. The reporter writes a shared `schemaVer
|
|
|
282
286
|
|
|
283
287
|
## 13. Experimental `@agent-inspect/jest` APIs
|
|
284
288
|
|
|
285
|
-
`@agent-inspect/jest` is an optional experimental workspace package for local Jest failure artifacts. It
|
|
289
|
+
`@agent-inspect/jest` is an optional experimental workspace package for local Jest failure artifacts. It is published with the fixed release group. It does not add a Jest dependency to root/core, does not upload artifacts, and does not infer trace relationships by timestamp.
|
|
286
290
|
|
|
287
291
|
Import from `@agent-inspect/jest`:
|
|
288
292
|
|
|
@@ -423,8 +427,8 @@ import type {
|
|
|
423
427
|
```
|
|
424
428
|
|
|
425
429
|
- **`TraceWriter`**: async `write(event)`, optional `flush()`, optional `close()`, optional `getStats()`.
|
|
426
|
-
- **`fileWriter({ dir?, filePath? })`**: appends `PersistedInspectEvent` JSONL rows to local disk. `createInspector()` emits schema 1.0 rows by default; compatibility adapters may still pass readable v0.2 rows. By default it derives one file per `event.runId`; `filePath` writes all events to an explicit local file. Filesystem and serialization failures are reflected in writer stats instead of being thrown into application code.
|
|
427
|
-
- **`bufferedFileWriter({ dir?, filePath?, maxQueueSize?, flushIntervalMs?, maxBatchSize?, overflow? })`**: buffers local JSONL writes with bounded queue behavior. Overflow supports `drop-oldest` and `drop-newest`; neither mode throws into application code.
|
|
430
|
+
- **`fileWriter({ dir?, filePath? })`**: appends `PersistedInspectEvent` JSONL rows to local disk. `createInspector()` emits schema 1.0 rows by default; compatibility adapters may still pass readable v0.2 rows. By default it derives one file per `event.runId`; `filePath` writes all events to an explicit local file. Filesystem and serialization failures are reflected in writer stats instead of being thrown into application code. Append-only local JSONL is diagnostic persistence — not a write-ahead log or fsync-guaranteed durable-before-effect journal.
|
|
431
|
+
- **`bufferedFileWriter({ dir?, filePath?, maxQueueSize?, flushIntervalMs?, maxBatchSize?, overflow? })`**: buffers local JSONL writes with bounded queue behavior. Overflow supports `drop-oldest` and `drop-newest`; neither mode throws into application code. On abrupt process exit, a bounded unflushed tail may be lost.
|
|
428
432
|
- **`compositeWriter([...writers])`**: fans out events to multiple explicit local/custom writers. A failing child writer does not prevent other children from receiving events; failures are reflected in composite stats.
|
|
429
433
|
- **`memoryWriter()`**: stores cloned `PersistedInspectEvent` rows in memory for tests, adapter fixtures, and eval harnesses.
|
|
430
434
|
- **`nullWriter()`**: accepts events without retaining them for disabled mode, overhead comparisons, and no-output tests.
|
|
@@ -433,7 +437,7 @@ No network writer or vendor sink exists in this package.
|
|
|
433
437
|
|
|
434
438
|
## 19. Experimental inspector API/runtime (v1.6)
|
|
435
439
|
|
|
436
|
-
`createInspector()` is the public instance API for local-first tracing with explicit writers. It owns an instance-specific runtime context, records schema 1.0 persisted inspect events, preserves application return values/errors, and exposes diagnostics plus deterministic `flush()`/`close()` lifecycle hooks.
|
|
440
|
+
`createInspector()` is the public instance API for local-first tracing with explicit writers. It owns an instance-specific runtime context, records schema 1.0 persisted inspect events, preserves application return values/errors, and exposes diagnostics plus deterministic `flush()`/`close()` lifecycle hooks (`flush`/`close` drain writer queues idempotently — they do not claim crash durability or fsync).
|
|
437
441
|
|
|
438
442
|
Import from `agent-inspect`:
|
|
439
443
|
|
|
@@ -537,7 +541,9 @@ import type { TraceCheckRule, TraceCheckResult, TraceFacts } from "agent-inspect
|
|
|
537
541
|
- **`TraceCheckRule`**: synchronous pure rule contract.
|
|
538
542
|
- **`TraceCheckResult`**: deterministic aggregate result with findings, evidence, summary counts, and execution diagnostics.
|
|
539
543
|
|
|
540
|
-
The checks API is experimental
|
|
544
|
+
The checks API is experimental. The `agent-inspect check` CLI uses this API for local reader-backed checks and deterministic JSON output; `agent-inspect artifacts` reuses the same safe findings for local CI artifact bundles and optional step-summary file output. Built-in rules operate on normalized event metadata, tree relationships, bounded summaries, token counts, and normalized baseline facts; safety and baseline findings identify event IDs and field paths rather than emitting raw prompts, outputs, secrets, headers, request/response bodies, or full tool payloads.
|
|
545
|
+
|
|
546
|
+
@beta Available through `agent-inspect/checks`. Additive changes may ship in minor releases; breaking changes require a future major.
|
|
541
547
|
|
|
542
548
|
Recipes: [deterministic-ci-checks](../examples/recipes/deterministic-ci-checks/README.md) for check/baseline/artifact workflows, and [test-reporter-artifacts](../examples/recipes/test-reporter-artifacts/README.md) for Vitest/Jest reporter configuration patterns.
|
|
543
549
|
|
package/docs/CLI.md
CHANGED
|
@@ -204,6 +204,8 @@ Options:
|
|
|
204
204
|
- `--refresh <ms>`: minimum time between renders
|
|
205
205
|
- `--json`: newline-delimited JSON updates
|
|
206
206
|
|
|
207
|
+
**Truncation recovery:** when a watched `--file` shrinks below the last read offset (for example a truncate-and-rewrite), `tail` resets the offset, discards any buffered partial line, and continues the same session from the start of the current file contents. Full inode-aware rename/recreate rotation is **not** claimed unless separately implemented and tested.
|
|
208
|
+
|
|
207
209
|
Important: `tail` is a local developer tool, not a production monitor.
|
|
208
210
|
|
|
209
211
|
### 6.6 `export`
|
package/docs/LIMITATIONS.md
CHANGED
|
@@ -23,6 +23,7 @@ This document states what AgentInspect **does not** provide today. It complement
|
|
|
23
23
|
|
|
24
24
|
- **Subpath APIs:** `agent-inspect/writers`, `agent-inspect/readers`, and advanced helpers are available for local adoption from their owning subpaths. `createInspector()` is part of the small root API.
|
|
25
25
|
- **Explicit writer ownership:** `createInspector()` does not print terminal lifecycle output or implicitly choose a disk writer. Use `fileWriter()` / `bufferedFileWriter()` / custom writers when persistence is desired.
|
|
26
|
+
- **Diagnostic evidence, not an event-sourced runtime:** AgentInspect traces are local diagnostic evidence of what an agent did. They are **not** a write-ahead log, durable-before-effect journal, or application event-sourcing runtime. Buffered writers may lose a bounded tail of events on abrupt process termination. Call `flush()` / `close()` according to writer docs when you need the queue drained before exit; that lifecycle is deterministic and idempotent, but it is **not** an fsync / crash-durability guarantee.
|
|
26
27
|
- **No standards upload:** OpenInference and OTLP JSON support is local read/export compatibility only. There is no OTLP gRPC/HTTP streaming sink, collector client, or hosted ingestion behavior.
|
|
27
28
|
- **Conservative detection:** `agent-inspect open` does not silently accept arbitrary JSON. Unsupported or ambiguous inputs produce errors/warnings rather than guessed traces.
|
|
28
29
|
- **Large inputs:** reader inputs are bounded and read into local memory. This is not a database index or production log warehouse.
|
package/docs/TRACE-CONTRACTS.md
CHANGED
|
@@ -14,6 +14,36 @@ Contracts compile to deterministic check rules for common cases:
|
|
|
14
14
|
- evidence-bearing findings on failures
|
|
15
15
|
- evaluation over **logical** TraceFacts (raw events remain available)
|
|
16
16
|
|
|
17
|
+
## `tools.requiredOrder` semantics
|
|
18
|
+
|
|
19
|
+
`requiredOrder` is expanded into **adjacent pair** ordering rules with unique ids:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
[A, B, C]
|
|
23
|
+
→ contract.tool.order.0: A before B
|
|
24
|
+
→ contract.tool.order.1: B before C
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Each pair compares the **first occurrence** (start/encounter order in the evaluated event stream):
|
|
28
|
+
|
|
29
|
+
- unlisted intermediate tools are allowed;
|
|
30
|
+
- later repetitions do not invalidate an earlier valid first-occurrence order;
|
|
31
|
+
- TraceContract `requiredOrder` **implies presence** — every listed name is added to the effective required-tool set;
|
|
32
|
+
- this is **not** causal happens-before; overlapping intervals emit a non-failing `tool.order.overlap` warning;
|
|
33
|
+
- combine ordering with `maxCalls` or custom rules when repeated calls matter.
|
|
34
|
+
|
|
35
|
+
Examples for `requiredOrder: ["retrieve", "generate"]`:
|
|
36
|
+
|
|
37
|
+
| Trajectory | Result |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `retrieve → generate` | PASS |
|
|
40
|
+
| `retrieve → rerank → generate` | PASS |
|
|
41
|
+
| `retrieve → generate → retrieve` | PASS (first-occurrence) |
|
|
42
|
+
| `generate → retrieve` | FAIL (order) |
|
|
43
|
+
| `cache_lookup → generate` | FAIL (missing `retrieve` via implied presence) |
|
|
44
|
+
|
|
45
|
+
Low-level `createToolOrderingRule({ before, after })` alone may still pass when an endpoint is missing (compositional). TraceContract `requiredOrder` does not.
|
|
46
|
+
|
|
17
47
|
### Experimental Vitest / Jest matchers (shipped)
|
|
18
48
|
|
|
19
49
|
| Package | Export | Matchers |
|
|
@@ -25,6 +55,66 @@ These are **Experimental** — API names may evolve. There is no `expectTrace(..
|
|
|
25
55
|
|
|
26
56
|
See [API.md](./API.md), [TRACE-FACTS.md](./TRACE-FACTS.md), and `packages/core/src/checks/contract.ts`.
|
|
27
57
|
|
|
58
|
+
## Rule kinds (shipped vs planned)
|
|
59
|
+
|
|
60
|
+
TraceContract rules fall into distinct categories. Mixing them incorrectly is a common source of false failures (see GitHub #308 and #309).
|
|
61
|
+
|
|
62
|
+
### `tools.required` (shipped)
|
|
63
|
+
|
|
64
|
+
Unconditional path invariant: every named tool must appear **at least once** in the trace.
|
|
65
|
+
|
|
66
|
+
- Use when the tool is always part of a valid execution path.
|
|
67
|
+
- **Do not** use for steps that legitimate shortcuts may skip (for example cache hits that bypass `retrieve`).
|
|
68
|
+
- When a shortcut is valid but you still need evidence of the outcome, prefer `observations.required` until `alternatives.anyOf` ships (6.20.0).
|
|
69
|
+
|
|
70
|
+
### `tools.requiredOrder` (shipped — first-occurrence / start-encounter)
|
|
71
|
+
|
|
72
|
+
Legacy first-start / encounter ordering. The evaluator walks the trace and checks that each listed tool's **first occurrence** appears after the previous tool's first occurrence.
|
|
73
|
+
|
|
74
|
+
- TraceContract `requiredOrder` **implies presence** of every listed tool (unioned into `tools.required`).
|
|
75
|
+
- Default mode is **first-occurrence** start/encounter order — **not** causal happens-before.
|
|
76
|
+
- Overlapping intervals that still satisfy start order emit a non-failing overlap warning.
|
|
77
|
+
- **Planned (6.20.0, GitHub #308):**
|
|
78
|
+
- `requiredOrderMode: "happens-before"` — first before must **end** before first after **starts**
|
|
79
|
+
- `requiredOrderMode: "all-occurrences"` — every before must end before every after starts
|
|
80
|
+
|
|
81
|
+
### `observations.required` (shipped)
|
|
82
|
+
|
|
83
|
+
Requires externally observed or effect evidence (for example HTTP status, file write, cache key) rather than a specific tool call. Prefer this when the invariant is about **outcome** rather than **which tool ran**.
|
|
84
|
+
|
|
85
|
+
### Planned (6.20.0 — not shipped)
|
|
86
|
+
|
|
87
|
+
Document only; **do not** use these fields in contracts today:
|
|
88
|
+
|
|
89
|
+
| Planned field | Purpose | GitHub |
|
|
90
|
+
|---------------|---------|--------|
|
|
91
|
+
| `alternatives.anyOf` | One of several deterministic valid paths (one level, no nested groups, no predicates) | #309 |
|
|
92
|
+
| `requiredOrderMode: "happens-before"` | Causal completion-before-start ordering | #308 |
|
|
93
|
+
| `requiredOrderMode: "all-occurrences"` | Strict ordering across all tool occurrences | #308 |
|
|
94
|
+
|
|
95
|
+
API shape for both requires maintainer approval before external PR lands. @HsienW volunteered on #308 for `requiredOrderMode` implementation.
|
|
96
|
+
|
|
97
|
+
## Workaround until 6.20.0
|
|
98
|
+
|
|
99
|
+
When a legitimate shortcut skips a tool you would otherwise require:
|
|
100
|
+
|
|
101
|
+
1. **Remove** unconditional `tools.required` for that step.
|
|
102
|
+
2. **Express** the verified outcome via `observations.required` when possible.
|
|
103
|
+
3. **Document** the cache-hit or alternate path in contract comments for reviewers.
|
|
104
|
+
|
|
105
|
+
Example matching GitHub #309 (cache hit skips second `retrieve`):
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
contract:
|
|
109
|
+
tools:
|
|
110
|
+
required: [generate] # not retrieve — cache may skip it
|
|
111
|
+
requiredOrder: [generate] # ordering only among tools that ran
|
|
112
|
+
observations:
|
|
113
|
+
required: [cache_hit_or_retrieve_evidence]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
With first-occurrence ordering, `retrieve → generate → retrieve` still **passes** when both retrieves are present (see worked example below).
|
|
117
|
+
|
|
28
118
|
## What is not shipped (yet)
|
|
29
119
|
|
|
30
120
|
Do **not** document these as available:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-inspect",
|
|
3
|
-
"version": "6.17.
|
|
3
|
+
"version": "6.17.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Local evidence debugger and trajectory-test toolkit for TypeScript AI agents — execution trees, TraceContract checks, Evidence v2, and read-only MCP",
|
|
@@ -239,10 +239,12 @@
|
|
|
239
239
|
"linked-versions:check": "node scripts/check-linked-versions.mjs",
|
|
240
240
|
"docs:commands": "node scripts/validate-doc-commands.mjs",
|
|
241
241
|
"docs:links": "node scripts/validate-doc-links.mjs",
|
|
242
|
+
"public-truth:sync": "node scripts/sync-public-truth.mjs",
|
|
242
243
|
"public-truth:check": "node scripts/validate-public-truth.mjs",
|
|
243
244
|
"ai-assets:check": "node scripts/validate-ai-assets.mjs",
|
|
244
245
|
"package-readmes:check": "node scripts/validate-package-readmes.mjs",
|
|
245
|
-
"docs:check": "pnpm run docs:commands && pnpm run docs:links && pnpm run public-truth:check && pnpm run ai-assets:check && pnpm run package-readmes:check && pnpm run repo:health && pnpm run demo:verify",
|
|
246
|
+
"docs:check": "pnpm run docs:commands && pnpm run docs:links && pnpm run public-truth:check && pnpm run ai-assets:check && pnpm run package-readmes:check && pnpm run repo:health && pnpm run build:cli && pnpm run demo:verify",
|
|
247
|
+
"build:cli": "pnpm exec tsup --config tsup.cli.config.ts",
|
|
246
248
|
"repo:health": "node scripts/validate-repo-health.mjs",
|
|
247
249
|
"demo:generate": "node scripts/demo-generate.mjs",
|
|
248
250
|
"demo:verify": "node scripts/demo-verify.mjs",
|
|
@@ -252,6 +254,7 @@
|
|
|
252
254
|
"perf:baseline": "node scripts/performance-baseline.mjs",
|
|
253
255
|
"examples:check": "pnpm install && pnpm --filter agent-inspect-example-01-basic run start",
|
|
254
256
|
"changeset": "changeset",
|
|
257
|
+
"version:packages": "changeset version && pnpm public-truth:sync && pnpm public-truth:check",
|
|
255
258
|
"release": "changeset publish",
|
|
256
259
|
"website:dev": "pnpm --filter @agent-inspect/website dev",
|
|
257
260
|
"website:build": "pnpm --filter @agent-inspect/website build",
|
|
@@ -3230,14 +3230,15 @@ function enrichSessionSummary(summary, runs, options = {}) {
|
|
|
3230
3230
|
|
|
3231
3231
|
// packages/core/src/sessions/checks.ts
|
|
3232
3232
|
function emptySummary() {
|
|
3233
|
-
return { passed: 0, failed: 0, warnings: 0, errors: 0 };
|
|
3233
|
+
return { passed: 0, failed: 0, warnings: 0, errors: 0, rulesEvaluated: 0 };
|
|
3234
3234
|
}
|
|
3235
3235
|
function mergeSummary(target, source) {
|
|
3236
3236
|
return {
|
|
3237
3237
|
passed: target.passed + source.passed,
|
|
3238
3238
|
failed: target.failed + source.failed,
|
|
3239
3239
|
warnings: target.warnings + source.warnings,
|
|
3240
|
-
errors: target.errors + source.errors
|
|
3240
|
+
errors: target.errors + source.errors,
|
|
3241
|
+
rulesEvaluated: target.rulesEvaluated + source.rulesEvaluated
|
|
3241
3242
|
};
|
|
3242
3243
|
}
|
|
3243
3244
|
function sessionDiagnostic(code, message) {
|
|
@@ -3261,6 +3262,7 @@ function aggregateSessionCheckResults(perRun, scope) {
|
|
|
3261
3262
|
`${scope.scopeKind} not found: ${scope.scopeLabel}`
|
|
3262
3263
|
)
|
|
3263
3264
|
],
|
|
3265
|
+
ruleExecutions: [],
|
|
3264
3266
|
...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
|
|
3265
3267
|
};
|
|
3266
3268
|
}
|
|
@@ -3281,17 +3283,20 @@ function aggregateSessionCheckResults(perRun, scope) {
|
|
|
3281
3283
|
`No readable traces in ${scope.scopeKind}: ${scope.scopeLabel}`
|
|
3282
3284
|
)
|
|
3283
3285
|
],
|
|
3286
|
+
ruleExecutions: [],
|
|
3284
3287
|
...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
|
|
3285
3288
|
};
|
|
3286
3289
|
}
|
|
3287
3290
|
let summary = emptySummary();
|
|
3288
3291
|
const findings = [];
|
|
3289
3292
|
const diagnostics = [];
|
|
3293
|
+
const ruleExecutions = [];
|
|
3290
3294
|
const runResults = [];
|
|
3291
3295
|
for (const result of perRun) {
|
|
3292
3296
|
summary = mergeSummary(summary, result.summary);
|
|
3293
3297
|
findings.push(...result.findings);
|
|
3294
3298
|
diagnostics.push(...result.diagnostics);
|
|
3299
|
+
ruleExecutions.push(...result.ruleExecutions ?? []);
|
|
3295
3300
|
if (result.runId) {
|
|
3296
3301
|
runResults.push({ runId: result.runId, status: result.status });
|
|
3297
3302
|
}
|
|
@@ -3304,6 +3309,11 @@ function aggregateSessionCheckResults(perRun, scope) {
|
|
|
3304
3309
|
if (runCmp !== 0) return runCmp;
|
|
3305
3310
|
return a.ruleId.localeCompare(b.ruleId);
|
|
3306
3311
|
});
|
|
3312
|
+
ruleExecutions.sort((a, b) => {
|
|
3313
|
+
const runCmp = (a.runId ?? "").localeCompare(b.runId ?? "");
|
|
3314
|
+
if (runCmp !== 0) return runCmp;
|
|
3315
|
+
return a.ruleId.localeCompare(b.ruleId);
|
|
3316
|
+
});
|
|
3307
3317
|
const hasErrors = diagnostics.some((item) => item.severity === "error");
|
|
3308
3318
|
const status = hasErrors ? "error" : summary.failed > 0 ? "fail" : "pass";
|
|
3309
3319
|
return {
|
|
@@ -3317,6 +3327,7 @@ function aggregateSessionCheckResults(perRun, scope) {
|
|
|
3317
3327
|
summary,
|
|
3318
3328
|
findings,
|
|
3319
3329
|
diagnostics,
|
|
3330
|
+
ruleExecutions,
|
|
3320
3331
|
...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
|
|
3321
3332
|
};
|
|
3322
3333
|
}
|
|
@@ -6401,10 +6412,11 @@ function emptySummary2() {
|
|
|
6401
6412
|
passed: 0,
|
|
6402
6413
|
failed: 0,
|
|
6403
6414
|
warnings: 0,
|
|
6404
|
-
errors: 0
|
|
6415
|
+
errors: 0,
|
|
6416
|
+
rulesEvaluated: 0
|
|
6405
6417
|
};
|
|
6406
6418
|
}
|
|
6407
|
-
function errorResult(input, diagnostics, selectedRun) {
|
|
6419
|
+
function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
|
|
6408
6420
|
return {
|
|
6409
6421
|
ok: false,
|
|
6410
6422
|
status: "error",
|
|
@@ -6412,10 +6424,12 @@ function errorResult(input, diagnostics, selectedRun) {
|
|
|
6412
6424
|
...selectedRun ? { runId: selectedRun.runId } : {},
|
|
6413
6425
|
summary: {
|
|
6414
6426
|
...emptySummary2(),
|
|
6415
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
6427
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
6428
|
+
rulesEvaluated: ruleExecutions.length
|
|
6416
6429
|
},
|
|
6417
6430
|
findings: [],
|
|
6418
|
-
diagnostics: [...diagnostics]
|
|
6431
|
+
diagnostics: [...diagnostics],
|
|
6432
|
+
ruleExecutions: [...ruleExecutions]
|
|
6419
6433
|
};
|
|
6420
6434
|
}
|
|
6421
6435
|
function flattenNodes(nodes) {
|
|
@@ -6571,7 +6585,7 @@ function normalizeFinding(rule, finding) {
|
|
|
6571
6585
|
...finding.action !== void 0 ? { action: finding.action } : {}
|
|
6572
6586
|
};
|
|
6573
6587
|
}
|
|
6574
|
-
function summarize(findings, diagnostics) {
|
|
6588
|
+
function summarize(findings, diagnostics, rulesEvaluated) {
|
|
6575
6589
|
return {
|
|
6576
6590
|
passed: findings.filter((finding) => finding.status === "pass").length,
|
|
6577
6591
|
failed: findings.filter(
|
|
@@ -6580,9 +6594,21 @@ function summarize(findings, diagnostics) {
|
|
|
6580
6594
|
warnings: findings.filter(
|
|
6581
6595
|
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
6582
6596
|
).length,
|
|
6583
|
-
errors: diagnostics.filter((item) => item.severity === "error").length
|
|
6597
|
+
errors: diagnostics.filter((item) => item.severity === "error").length,
|
|
6598
|
+
rulesEvaluated
|
|
6584
6599
|
};
|
|
6585
6600
|
}
|
|
6601
|
+
function classifyRuleExecution(findings, threw) {
|
|
6602
|
+
if (findings.some((finding) => finding.status === "fail" && finding.severity === "error")) {
|
|
6603
|
+
return "fail";
|
|
6604
|
+
}
|
|
6605
|
+
if (findings.some(
|
|
6606
|
+
(finding) => finding.status === "warning" || finding.severity === "warning"
|
|
6607
|
+
)) {
|
|
6608
|
+
return "warning";
|
|
6609
|
+
}
|
|
6610
|
+
return "pass";
|
|
6611
|
+
}
|
|
6586
6612
|
function stringAttr(event, keys) {
|
|
6587
6613
|
for (const key of keys) {
|
|
6588
6614
|
const value = event.attributes?.[key];
|
|
@@ -6679,6 +6705,9 @@ function finishedEvents(context, kind) {
|
|
|
6679
6705
|
(event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
|
|
6680
6706
|
);
|
|
6681
6707
|
}
|
|
6708
|
+
function toolInvocationEvents(context) {
|
|
6709
|
+
return semanticEvents(context).filter((event) => event.kind === "TOOL");
|
|
6710
|
+
}
|
|
6682
6711
|
function isRecord8(value) {
|
|
6683
6712
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6684
6713
|
}
|
|
@@ -7079,7 +7108,7 @@ function createToolUsageRule(options) {
|
|
|
7079
7108
|
category: "tool",
|
|
7080
7109
|
defaultSeverity: "error",
|
|
7081
7110
|
evaluate(context) {
|
|
7082
|
-
const tools =
|
|
7111
|
+
const tools = toolInvocationEvents(context);
|
|
7083
7112
|
const names = tools.map(toolName);
|
|
7084
7113
|
const nameSet = new Set(names);
|
|
7085
7114
|
const findings = [];
|
|
@@ -7729,12 +7758,24 @@ function createBaselineRegressionRule(options) {
|
|
|
7729
7758
|
}
|
|
7730
7759
|
function createObservedOutcomeRule(options = {}) {
|
|
7731
7760
|
const failOn = options.failOn ?? ["failed"];
|
|
7761
|
+
const requireAny = options.requireAny === true;
|
|
7732
7762
|
return {
|
|
7733
7763
|
id: "outcome.status",
|
|
7734
7764
|
category: "run",
|
|
7735
7765
|
defaultSeverity: "error",
|
|
7736
7766
|
evaluate(context) {
|
|
7737
7767
|
const outcomes = extractOutcomesFromPersistedEvents(context.events);
|
|
7768
|
+
if (requireAny && outcomes.length === 0) {
|
|
7769
|
+
return [
|
|
7770
|
+
failFinding(
|
|
7771
|
+
"outcome.status",
|
|
7772
|
+
"Expected at least one observed outcome.",
|
|
7773
|
+
runEvidence(context.selectedRun),
|
|
7774
|
+
{ requireAny: true, expected: "at least one observed outcome" },
|
|
7775
|
+
{ code: "outcome.missing", actual: 0 }
|
|
7776
|
+
)
|
|
7777
|
+
];
|
|
7778
|
+
}
|
|
7738
7779
|
const matching = outcomesMatchingStatus(outcomes, failOn);
|
|
7739
7780
|
if (matching.length === 0) return [];
|
|
7740
7781
|
return [
|
|
@@ -7770,6 +7811,18 @@ function runTraceChecks(input, options = {}) {
|
|
|
7770
7811
|
if (rules.diagnostics.length > 0) {
|
|
7771
7812
|
return errorResult(input, rules.diagnostics, selected.run);
|
|
7772
7813
|
}
|
|
7814
|
+
if (rules.rules.length === 0) {
|
|
7815
|
+
return errorResult(
|
|
7816
|
+
input,
|
|
7817
|
+
[
|
|
7818
|
+
diagnostic3(
|
|
7819
|
+
"AI_CHECK_NO_RULES_EVALUATED",
|
|
7820
|
+
"No trace check rules were evaluated. Configure at least one rule, contract, or CLI check option."
|
|
7821
|
+
)
|
|
7822
|
+
],
|
|
7823
|
+
selected.run
|
|
7824
|
+
);
|
|
7825
|
+
}
|
|
7773
7826
|
const facts = buildFacts2(input, selected.run);
|
|
7774
7827
|
const context = {
|
|
7775
7828
|
...facts,
|
|
@@ -7778,22 +7831,38 @@ function runTraceChecks(input, options = {}) {
|
|
|
7778
7831
|
};
|
|
7779
7832
|
const diagnostics = [];
|
|
7780
7833
|
const findings = [];
|
|
7834
|
+
const ruleExecutions = [];
|
|
7781
7835
|
for (const rule of rules.rules) {
|
|
7782
7836
|
try {
|
|
7783
|
-
|
|
7837
|
+
const ruleFindings = rule.evaluate(context).map((finding) => normalizeFinding(rule, finding));
|
|
7838
|
+
findings.push(...ruleFindings);
|
|
7839
|
+
ruleExecutions.push({
|
|
7840
|
+
ruleId: rule.id,
|
|
7841
|
+
category: rule.category,
|
|
7842
|
+
status: classifyRuleExecution(ruleFindings, false),
|
|
7843
|
+
findingCount: ruleFindings.length,
|
|
7844
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
7845
|
+
});
|
|
7784
7846
|
} catch (error) {
|
|
7785
7847
|
const message = error instanceof Error ? error.message : String(error);
|
|
7786
7848
|
diagnostics.push(
|
|
7787
7849
|
diagnostic3("AI_CHECK_INTERNAL_ERROR", `Rule ${rule.id} failed: ${message}`, rule.id)
|
|
7788
7850
|
);
|
|
7851
|
+
ruleExecutions.push({
|
|
7852
|
+
ruleId: rule.id,
|
|
7853
|
+
category: rule.category,
|
|
7854
|
+
status: "error",
|
|
7855
|
+
findingCount: 0,
|
|
7856
|
+
...selected.run ? { runId: selected.run.runId } : {}
|
|
7857
|
+
});
|
|
7789
7858
|
}
|
|
7790
7859
|
}
|
|
7791
7860
|
if (diagnostics.length > 0) {
|
|
7792
|
-
return errorResult(input, diagnostics, selected.run);
|
|
7861
|
+
return errorResult(input, diagnostics, selected.run, ruleExecutions);
|
|
7793
7862
|
}
|
|
7794
7863
|
const eventById = new Map(input.read.events.map((event) => [event.eventId, event]));
|
|
7795
7864
|
const sortedFindings = findings.sort(compareFindings(eventById));
|
|
7796
|
-
const summary = summarize(sortedFindings, diagnostics);
|
|
7865
|
+
const summary = summarize(sortedFindings, diagnostics, ruleExecutions.length);
|
|
7797
7866
|
const status = summary.failed > 0 ? "fail" : "pass";
|
|
7798
7867
|
return {
|
|
7799
7868
|
ok: status === "pass",
|
|
@@ -7802,7 +7871,8 @@ function runTraceChecks(input, options = {}) {
|
|
|
7802
7871
|
...selected.run ? { runId: selected.run.runId } : {},
|
|
7803
7872
|
summary,
|
|
7804
7873
|
findings: sortedFindings,
|
|
7805
|
-
diagnostics
|
|
7874
|
+
diagnostics,
|
|
7875
|
+
ruleExecutions
|
|
7806
7876
|
};
|
|
7807
7877
|
}
|
|
7808
7878
|
|
|
@@ -10166,8 +10236,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
10166
10236
|
status: "pass",
|
|
10167
10237
|
format: read.format,
|
|
10168
10238
|
findings: [],
|
|
10169
|
-
diagnostics: []
|
|
10170
|
-
};
|
|
10239
|
+
diagnostics: []};
|
|
10171
10240
|
const observationResult = validateExpectedObservations(suiteCase, read);
|
|
10172
10241
|
const diagnostics = [
|
|
10173
10242
|
...checkResult.diagnostics.map(
|
|
@@ -11346,5 +11415,5 @@ function renderGateReport(result, options = {}) {
|
|
|
11346
11415
|
}
|
|
11347
11416
|
|
|
11348
11417
|
export { COHORT_METRIC_IDS, DEFAULT_SUITE_ARTIFACTS_DIR, EVIDENCE_FORMAT_VERSION, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, Redactor, TraceDirectory, TraceReadError, TreeBuilder, aggregateBundleSafeStatus, aggregateSessionCheckResults, analyzeCohort, applyProfileMetadataCaps, assertBundlePathContained, assertEvidenceRelativePath, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceCausalFailureViewHtml, buildEvidenceCiPackage, buildEvidenceCircuitViewHtml, buildEvidenceContractsViewHtml, buildEvidenceDiffViewHtml, buildEvidenceHtmlShell, buildEvidenceManifest, buildEvidenceOutcomesViewHtml, buildEvidenceProvenanceViewHtml, buildEvidenceSafetyViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceTreeViewHtml, buildLocalExplanation, buildPlaceholderArtifact, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, buildZipArchive, bundleFailsOnSafety, bundleRunAssetRelativePath, collectTraceSchemaVersions, compactAttributes, createBaselineRegressionRule, createLlmUsageRule, createMaxStepDurationRule, createObservedOutcomeRule, createRequireCompletedRule, createRunDepthRule, createRunDurationRule, createRunStatusRule, createSafetyOversizedAttributeRule, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createStallDetectionRule, createStructureCycleRule, createStructureOrphanRule, createStructureParallelWidthRule, createStructureRelationshipRule, createToolUsageRule, defaultBundleOutputPath, defaultSuiteConfigTemplate, diffRuns, diffTraceEvents, enrichSessionRunRecord, escapeHtml, escapeMarkdown, extractMetadata, extractOutcomesFromTraceEvents, filterMetasBySessionScope, filterTraces, flattenTree, formatDuration2 as formatDuration, formatStepLabel, formatTimestamp, gateHasThresholds, getIndent, getTraceFilePath, inferEvidenceFileRole, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, manualTraceEventsToComparableRun, nanoid, normalizeBundleOutputPath, openTrace, parseCohortMetricList, parseDuration, parseDurationFilter, parseGateList, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderCohortReport, renderErrorLine, renderGateReport, renderObservedOutcomesHtml, renderObservedOutcomesMarkdown, renderRunDiff, renderRunWhat, renderStepLine, renderSuiteReport, renderTimeline, renderTraceStats, resolveBundleRunIds, resolveRedactionProfile, resolveSuiteTemplate, resolveTraceDir, runGate, runSuite, runTraceChecks, safeString, sanitizeBundleRunId, searchTraces, serializeEvidenceManifest, sha256Hex, stableJson, summarizeObservedOutcomes, summarizeSemanticParity, traceEventToPersistedInspectEvent, truncateName, truncateStringForProfile, validateEvent, validateSuiteConfig, verifyEvidenceDirectory, zeroKinds };
|
|
11349
|
-
//# sourceMappingURL=chunk-
|
|
11350
|
-
//# sourceMappingURL=chunk-
|
|
11418
|
+
//# sourceMappingURL=chunk-GOHYSE7W.mjs.map
|
|
11419
|
+
//# sourceMappingURL=chunk-GOHYSE7W.mjs.map
|