agent-inspect 4.3.0 → 4.4.0

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.
Files changed (97) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/docs/API.md +3 -0
  3. package/docs/CLI.md +3 -0
  4. package/docs/SCHEMA.md +27 -1
  5. package/package.json +1 -1
  6. package/packages/cli/dist/{chunk-BS5LSKZ3.mjs → chunk-ORHDQUT6.mjs} +198 -7
  7. package/packages/cli/dist/chunk-ORHDQUT6.mjs.map +1 -0
  8. package/packages/cli/dist/index.cjs +409 -17
  9. package/packages/cli/dist/index.cjs.map +1 -1
  10. package/packages/cli/dist/index.mjs +176 -10
  11. package/packages/cli/dist/index.mjs.map +1 -1
  12. package/packages/cli/dist/{src-YFMPWEIS.mjs → src-FJOHPC4X.mjs} +3 -3
  13. package/packages/cli/dist/{src-YFMPWEIS.mjs.map → src-FJOHPC4X.mjs.map} +1 -1
  14. package/packages/core/dist/advanced.cjs +201 -9
  15. package/packages/core/dist/advanced.cjs.map +1 -1
  16. package/packages/core/dist/advanced.d.cts +12 -8
  17. package/packages/core/dist/advanced.d.ts +12 -8
  18. package/packages/core/dist/advanced.mjs +30 -13
  19. package/packages/core/dist/advanced.mjs.map +1 -1
  20. package/packages/core/dist/checks.cjs +117 -18
  21. package/packages/core/dist/checks.cjs.map +1 -1
  22. package/packages/core/dist/checks.d.cts +11 -3
  23. package/packages/core/dist/checks.d.ts +11 -3
  24. package/packages/core/dist/checks.mjs +42 -1
  25. package/packages/core/dist/checks.mjs.map +1 -1
  26. package/packages/core/dist/{chunk-2ZXEMWGK.mjs → chunk-3USJVBLA.mjs} +3 -3
  27. package/packages/core/dist/{chunk-2ZXEMWGK.mjs.map → chunk-3USJVBLA.mjs.map} +1 -1
  28. package/packages/core/dist/{chunk-HY7H3CQM.mjs → chunk-CAWPF22J.mjs} +4 -3
  29. package/packages/core/dist/chunk-CAWPF22J.mjs.map +1 -0
  30. package/packages/core/dist/{chunk-XUNJMAPD.mjs → chunk-KNYL56KZ.mjs} +38 -3
  31. package/packages/core/dist/chunk-KNYL56KZ.mjs.map +1 -0
  32. package/packages/core/dist/{chunk-IZBJAZGF.mjs → chunk-P366CCL2.mjs} +34 -3
  33. package/packages/core/dist/chunk-P366CCL2.mjs.map +1 -0
  34. package/packages/core/dist/{chunk-4JVGFNQH.mjs → chunk-ULCGIRTC.mjs} +95 -8
  35. package/packages/core/dist/chunk-ULCGIRTC.mjs.map +1 -0
  36. package/packages/core/dist/chunk-VFO76UH3.mjs +228 -0
  37. package/packages/core/dist/chunk-VFO76UH3.mjs.map +1 -0
  38. package/packages/core/dist/{chunk-NQZPZ2FN.mjs → chunk-WRE4CNPF.mjs} +6 -3
  39. package/packages/core/dist/chunk-WRE4CNPF.mjs.map +1 -0
  40. package/packages/core/dist/{chunk-A4V2H3YU.mjs → chunk-ZWA5RWMV.mjs} +40 -4
  41. package/packages/core/dist/chunk-ZWA5RWMV.mjs.map +1 -0
  42. package/packages/core/dist/{context-DjY-jvQk.d.cts → context-BbfkMYjz.d.cts} +5 -3
  43. package/packages/core/dist/{context-BDZmi53V.d.ts → context-Cp8NRbBX.d.ts} +5 -3
  44. package/packages/core/dist/diff.cjs.map +1 -1
  45. package/packages/core/dist/diff.d.cts +3 -3
  46. package/packages/core/dist/diff.d.ts +3 -3
  47. package/packages/core/dist/diff.mjs +1 -1
  48. package/packages/core/dist/exporters.cjs +137 -1
  49. package/packages/core/dist/exporters.cjs.map +1 -1
  50. package/packages/core/dist/exporters.d.cts +6 -3
  51. package/packages/core/dist/exporters.d.ts +6 -3
  52. package/packages/core/dist/exporters.mjs +71 -6
  53. package/packages/core/dist/exporters.mjs.map +1 -1
  54. package/packages/core/dist/index.cjs +181 -6
  55. package/packages/core/dist/index.cjs.map +1 -1
  56. package/packages/core/dist/index.d.cts +14 -7
  57. package/packages/core/dist/index.d.ts +14 -7
  58. package/packages/core/dist/index.mjs +51 -7
  59. package/packages/core/dist/index.mjs.map +1 -1
  60. package/packages/core/dist/{inspect-event-CYAV7Hxm.d.cts → inspect-event-IqwOHbGo.d.cts} +1 -1
  61. package/packages/core/dist/{inspect-event-CYAV7Hxm.d.ts → inspect-event-IqwOHbGo.d.ts} +1 -1
  62. package/packages/core/dist/{log-config-BNQ9UTmP.d.cts → log-config-CW8w5YQ9.d.cts} +1 -1
  63. package/packages/core/dist/{log-config-D3Yp1SZN.d.ts → log-config-SRA4xTp8.d.ts} +1 -1
  64. package/packages/core/dist/logs.d.cts +3 -3
  65. package/packages/core/dist/logs.d.ts +3 -3
  66. package/packages/core/dist/{persisted-inspect-event-BLvb0jSX.d.ts → persisted-inspect-event-DruwqARZ.d.ts} +1 -1
  67. package/packages/core/dist/{persisted-inspect-event-D5SjBz9b.d.cts → persisted-inspect-event-Gd-W8vB7.d.cts} +1 -1
  68. package/packages/core/dist/persisted.cjs +67 -1
  69. package/packages/core/dist/persisted.cjs.map +1 -1
  70. package/packages/core/dist/persisted.d.cts +5 -5
  71. package/packages/core/dist/persisted.d.ts +5 -5
  72. package/packages/core/dist/persisted.mjs +3 -3
  73. package/packages/core/dist/readers.cjs +72 -3
  74. package/packages/core/dist/readers.cjs.map +1 -1
  75. package/packages/core/dist/readers.d.cts +2 -2
  76. package/packages/core/dist/readers.d.ts +2 -2
  77. package/packages/core/dist/readers.mjs +5 -5
  78. package/packages/core/dist/readers.mjs.map +1 -1
  79. package/packages/core/dist/{types-CQun9LW6.d.ts → types-B1X87dUW.d.cts} +16 -2
  80. package/packages/core/dist/{types-C-llnPH0.d.cts → types-BVkjSd0q.d.ts} +16 -2
  81. package/packages/core/dist/types-CvsKGweN.d.cts +12 -0
  82. package/packages/core/dist/types-CvsKGweN.d.ts +12 -0
  83. package/packages/core/dist/writers.cjs +2 -1
  84. package/packages/core/dist/writers.cjs.map +1 -1
  85. package/packages/core/dist/writers.d.cts +2 -2
  86. package/packages/core/dist/writers.d.ts +2 -2
  87. package/packages/core/dist/writers.mjs +3 -4
  88. package/packages/core/dist/writers.mjs.map +1 -1
  89. package/packages/cli/dist/chunk-BS5LSKZ3.mjs.map +0 -1
  90. package/packages/core/dist/chunk-4JVGFNQH.mjs.map +0 -1
  91. package/packages/core/dist/chunk-A4V2H3YU.mjs.map +0 -1
  92. package/packages/core/dist/chunk-EDTQHZPM.mjs +0 -88
  93. package/packages/core/dist/chunk-EDTQHZPM.mjs.map +0 -1
  94. package/packages/core/dist/chunk-HY7H3CQM.mjs.map +0 -1
  95. package/packages/core/dist/chunk-IZBJAZGF.mjs.map +0 -1
  96. package/packages/core/dist/chunk-NQZPZ2FN.mjs.map +0 -1
  97. package/packages/core/dist/chunk-XUNJMAPD.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 42635d8: Add observed outcomes (`observeOutcome`) with OUTCOME events, report/check/search integration, and redaction-bounded evidence fields.
8
+
3
9
  ## 4.3.0
4
10
 
5
11
  ### Minor Changes
package/docs/API.md CHANGED
@@ -84,6 +84,7 @@ import {
84
84
  - **`step.llm(model, fn)`**: convenience wrapper (`type: "llm"`, `metadata.model`).
85
85
  - **`step.tool(toolName, fn)`**: convenience wrapper (`type: "tool"`, `metadata.toolName`).
86
86
  - **`observe(agent, options?)`**: proxy wrapper that traces top-level `run` / `execute` / `invoke` methods via `inspectRun`.
87
+ - **`observeOutcome(name, options)`** (v4.4.0+): records an observed outcome (`outcome_observed`) inside an active `inspectRun` context. Requires `expectation` and `status` (`passed` | `failed` | `unknown` | `skipped`); optional `method`, `actual`, and `evidence`. Outside a run → warn and no-op (never throws). `actual` / `evidence` are bounded and redacted before disk.
87
88
  - **`getCurrentCorrelationMetadata()`**: returns active run correlation fields (`correlationId`, `requestId`, `decisionId`, `groupId`) inside `inspectRun` / `maybeInspectRun`; `undefined` outside a traced run or when none were set.
88
89
  - **`RedactionProfile`**: `"local" | "share" | "strict"` — see `redactionProfile` on `InspectRunOptions` and `ExportOptions`.
89
90
  - **`resolveRedactionProfile(profile?)`**: advanced helper available from `agent-inspect/advanced`; resolves profile extra keys and metadata caps for integrations.
@@ -109,6 +110,7 @@ These APIs support local workflows like listing traces, extracting metadata/summ
109
110
  - `RunCompletedEvent` (`event: "run_completed"`)
110
111
  - `StepStartedEvent` (`event: "step_started"`)
111
112
  - `StepCompletedEvent` (`event: "step_completed"`)
113
+ - `OutcomeObservedEvent` (`event: "outcome_observed"`, v4.4.0+)
112
114
  - Related types: `StepType`, `StepStatus`, `RunStatus`, `ErrorInfo`, `StepMetadata`, `TokenMetadata`
113
115
 
114
116
  ### Log-derived normalized model (stable as a model, not necessarily the parsing APIs)
@@ -460,6 +462,7 @@ Public methods:
460
462
  - **`step(name, fn, options?)`**: writes nested step lifecycle events when called inside the same inspector's run context; outside a context it passes through.
461
463
  - **`tool(name, fn, options?)`** / **`llm(name, fn, options?)`**: convenience wrappers that set `type` and metadata.
462
464
  - **`observe(name, fn, options?)`**: returns an async wrapper that records the function call as an inspector step.
465
+ - **`observeOutcome(name, options)`** (v4.4.0+): writes `outcome_observed` / `OUTCOME` events through the configured writer when inside an inspector run context.
463
466
  - **`getDiagnostics()`**: returns instrumentation error counts and writer stats without requiring direct runtime access.
464
467
  - **`flush()`** / **`close()`**: delegate to the configured writer through the runtime.
465
468
 
package/docs/CLI.md CHANGED
@@ -317,6 +317,7 @@ Options:
317
317
  - `--correlate-group`: when using `--session`, also match synthetic `group:` session keys
318
318
  - `--guardrails <rule>`: optional deterministic guardrail rules (`banned-phrase`, `pii-leak`, `prompt-injection`, …); repeatable
319
319
  - `--circuit <rule>`: optional circuit analyzers (`same-tool-repetition`, `max-retries`, …); repeatable
320
+ - `--fail-on-observation <status>`: add `outcome.status` rule; repeatable (`failed`, `passed`, `unknown`, `skipped`; default when flag present without value: `failed`)
320
321
 
321
322
  By default, `check` runs `run.status`. Additional built-in rules can be selected with `--rule` or config when their options are available.
322
323
 
@@ -667,6 +668,7 @@ Options:
667
668
  - `--limit <number>` — default 50
668
669
  - `--session <id>` — limit to runs in one workflow session
669
670
  - `--correlate-group` — when using `--session`, also match synthetic `group:` keys
671
+ - `--observation <status>` — filter runs with observed outcomes matching status (`passed`, `failed`, `unknown`, `skipped`)
670
672
  - `--json`
671
673
 
672
674
  Examples:
@@ -779,6 +781,7 @@ Options:
779
781
  - `-o, --output <path>` — write to file
780
782
  - `--json` — JSON wrapper (includes `content` when writing to stdout)
781
783
  - `--include-attributes` — bounded attributes in the execution tree section
784
+ - `--section <name>` — include report sections; repeatable (`what`, `timeline`, `tree`, `observations`; default: all except when narrowed)
782
785
  - `--no-errors` — omit error details from the execution tree section
783
786
  - `--no-correlation` — omit correlation ids from what section
784
787
  - `--redaction-profile <local|share|strict>` — key-based redaction profile applied to the complete report (default `local`); review output before sharing
package/docs/SCHEMA.md CHANGED
@@ -36,6 +36,7 @@ The stable event names are:
36
36
  - `run_completed`
37
37
  - `step_started`
38
38
  - `step_completed`
39
+ - `outcome_observed` (v4.4.0+)
39
40
 
40
41
  There is **no** `step_failed` event. Failures are represented by `step_completed` with `status: "error"`.
41
42
 
@@ -111,6 +112,31 @@ Every trace line contains:
111
112
  }
112
113
  ```
113
114
 
115
+ ### 3.5 `outcome_observed` (v4.4.0+)
116
+
117
+ Records whether an external side effect matched expectations. Distinct from step/tool success.
118
+
119
+ ```ts
120
+ {
121
+ schemaVersion: "0.1",
122
+ event: "outcome_observed",
123
+ timestamp: number,
124
+ runId: string,
125
+ outcomeId: string,
126
+ parentId?: string,
127
+ name: string,
128
+ expectation: string,
129
+ status: "passed" | "failed" | "unknown" | "skipped",
130
+ method?: "dom" | "accessibility" | "snapshot" | "network" | "storage"
131
+ | "filesystem" | "database" | "queue" | "custom",
132
+ actual?: unknown,
133
+ evidence?: Record<string, unknown>,
134
+ observedAt: number
135
+ }
136
+ ```
137
+
138
+ `actual` and `evidence` are bounded and redacted before disk like step metadata. See [OBSERVED-OUTCOMES-V4.4.md](./proposals/OBSERVED-OUTCOMES-V4.4.md).
139
+
114
140
  ## 4. Error representation
115
141
 
116
142
  - Errors are structured as `{ message, stack? }`.
@@ -173,7 +199,7 @@ interface InspectEvent {
173
199
  runId: string;
174
200
  parentId?: string;
175
201
  name: string;
176
- kind: "RUN" | "AGENT" | "LLM" | "TOOL" | "CHAIN" | "RETRIEVER" | "DECISION" | "RESULT" | "ERROR" | "LOGIC" | "LOG";
202
+ kind: "RUN" | "AGENT" | "LLM" | "TOOL" | "CHAIN" | "RETRIEVER" | "DECISION" | "RESULT" | "ERROR" | "LOGIC" | "LOG" | "OUTCOME";
177
203
  timestamp: number;
178
204
  status?: "running" | "ok" | "error";
179
205
  durationMs?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-inspect",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Trace, check, and safely share TypeScript AI-agent runs locally — no account, no upload, metadata-only by default",
@@ -52,7 +52,8 @@ var INSPECT_KINDS = [
52
52
  "RESULT",
53
53
  "ERROR",
54
54
  "LOGIC",
55
- "LOG"
55
+ "LOG",
56
+ "OUTCOME"
56
57
  ];
57
58
  var ATTRIBUTION_CONFIDENCES = [
58
59
  "explicit",
@@ -525,6 +526,32 @@ function fromLegacyStepCompleted(event) {
525
526
  if (error) out.error = error;
526
527
  return out;
527
528
  }
529
+ function fromLegacyOutcomeObserved(event) {
530
+ const attrs = event.attributes ?? {};
531
+ const observedAtRaw = attrs.observedAt;
532
+ const observedAt = typeof observedAtRaw === "string" ? Date.parse(observedAtRaw) : typeof observedAtRaw === "number" && Number.isFinite(observedAtRaw) ? observedAtRaw : resolveTimes(event).timestamp;
533
+ const status = attrs.outcomeStatus;
534
+ const out = {
535
+ schemaVersion: "0.1",
536
+ event: "outcome_observed",
537
+ timestamp: observedAt,
538
+ runId: event.runId,
539
+ outcomeId: typeof attrs.outcomeId === "string" ? attrs.outcomeId : event.eventId,
540
+ name: event.name,
541
+ expectation: typeof attrs.expectation === "string" ? attrs.expectation : event.name,
542
+ status: status === "passed" || status === "failed" || status === "unknown" || status === "skipped" ? status : "unknown",
543
+ observedAt
544
+ };
545
+ if (event.parentId !== void 0) out.parentId = event.parentId;
546
+ if (typeof attrs.method === "string") out.method = attrs.method;
547
+ if (attrs.actual !== void 0) out.actual = attrs.actual;
548
+ if (event.outputSummary !== void 0) out.actual = event.outputSummary;
549
+ if (attrs.evidence !== void 0) out.evidence = attrs.evidence;
550
+ return out;
551
+ }
552
+ function fromNativeOutcome(event) {
553
+ return [fromLegacyOutcomeObserved(event)];
554
+ }
528
555
  function fromNativeRun(event) {
529
556
  const { timestamp, startTime, endTime } = resolveTimes(event);
530
557
  const runStatus = mapPersistedStatusToRunStatus(event.status);
@@ -612,9 +639,13 @@ function persistedInspectEventToTraceEvents(event) {
612
639
  if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
613
640
  if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
614
641
  if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
642
+ if (legacyEvent === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
615
643
  if (event.kind === "RUN") {
616
644
  return fromNativeRun(event);
617
645
  }
646
+ if (event.kind === "OUTCOME") {
647
+ return fromNativeOutcome(event);
648
+ }
618
649
  return fromNativeStep(event);
619
650
  }
620
651
  function persistedInspectEventsToTraceEvents(events, options) {
@@ -663,6 +694,9 @@ function isTraceEvent(value) {
663
694
  case "step_completed": {
664
695
  return typeof value.runId === "string" && typeof value.stepId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
665
696
  }
697
+ case "outcome_observed": {
698
+ return typeof value.runId === "string" && typeof value.outcomeId === "string" && typeof value.name === "string" && typeof value.expectation === "string" && (value.status === "passed" || value.status === "failed" || value.status === "unknown" || value.status === "skipped") && typeof value.observedAt === "number";
699
+ }
666
700
  default:
667
701
  return false;
668
702
  }
@@ -973,6 +1007,9 @@ function validateEvent(event) {
973
1007
  case "step_completed": {
974
1008
  return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
975
1009
  }
1010
+ case "outcome_observed": {
1011
+ return nonEmptyString(event.runId) && nonEmptyString(event.outcomeId) && nonEmptyString(event.name) && nonEmptyString(event.expectation) && (event.status === "passed" || event.status === "failed" || event.status === "unknown" || event.status === "skipped") && finiteNumber(event.observedAt);
1012
+ }
976
1013
  default:
977
1014
  return false;
978
1015
  }
@@ -2512,6 +2549,142 @@ function renderTraceStats(stats) {
2512
2549
  return lines.join("\n");
2513
2550
  }
2514
2551
 
2552
+ // packages/core/src/outcomes/types.ts
2553
+ var OBSERVED_OUTCOME_STATUSES = [
2554
+ "passed",
2555
+ "failed",
2556
+ "unknown",
2557
+ "skipped"
2558
+ ];
2559
+ var OUTCOME_ATTRIBUTE_STATUS_KEY = "outcomeStatus";
2560
+ var OUTCOME_ATTRIBUTE_EXPECTATION_KEY = "expectation";
2561
+ var OUTCOME_ATTRIBUTE_METHOD_KEY = "method";
2562
+ var OUTCOME_ATTRIBUTE_OBSERVED_AT_KEY = "observedAt";
2563
+ var OUTCOME_LEGACY_EVENT = "outcome_observed";
2564
+
2565
+ // packages/core/src/outcomes/validate.ts
2566
+ function parseObservedOutcomeStatus(value) {
2567
+ const trimmed = value.trim().toLowerCase();
2568
+ if (OBSERVED_OUTCOME_STATUSES.includes(trimmed)) {
2569
+ return trimmed;
2570
+ }
2571
+ throw new Error(
2572
+ `Unsupported observation status "${value}". Use passed, failed, unknown, or skipped.`
2573
+ );
2574
+ }
2575
+
2576
+ // packages/core/src/outcomes/extract.ts
2577
+ function isOutcomeStatus(value) {
2578
+ return value === "passed" || value === "failed" || value === "unknown" || value === "skipped";
2579
+ }
2580
+ function parseMethod(value) {
2581
+ if (typeof value !== "string" || value.trim() === "") return void 0;
2582
+ return value;
2583
+ }
2584
+ function fromOutcomeObservedEvent(event) {
2585
+ return {
2586
+ outcomeId: event.outcomeId,
2587
+ runId: event.runId,
2588
+ ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
2589
+ name: event.name,
2590
+ expectation: event.expectation,
2591
+ status: event.status,
2592
+ ...event.method !== void 0 ? { method: event.method } : {},
2593
+ ...event.actual !== void 0 ? { actual: event.actual } : {},
2594
+ ...event.evidence !== void 0 ? { evidence: event.evidence } : {},
2595
+ observedAt: event.observedAt
2596
+ };
2597
+ }
2598
+ function fromPersistedOutcome(event) {
2599
+ if (event.kind !== "OUTCOME") return void 0;
2600
+ const attrs = event.attributes ?? {};
2601
+ const statusRaw = attrs[OUTCOME_ATTRIBUTE_STATUS_KEY];
2602
+ if (!isOutcomeStatus(statusRaw)) return void 0;
2603
+ const expectation = typeof attrs[OUTCOME_ATTRIBUTE_EXPECTATION_KEY] === "string" ? attrs[OUTCOME_ATTRIBUTE_EXPECTATION_KEY] : event.name;
2604
+ const observedAtRaw = attrs[OUTCOME_ATTRIBUTE_OBSERVED_AT_KEY];
2605
+ const observedAt = typeof observedAtRaw === "string" ? Date.parse(observedAtRaw) : typeof observedAtRaw === "number" && Number.isFinite(observedAtRaw) ? observedAtRaw : Date.parse(event.timestamp);
2606
+ return {
2607
+ outcomeId: event.eventId,
2608
+ runId: event.runId,
2609
+ ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
2610
+ name: event.name,
2611
+ expectation,
2612
+ status: statusRaw,
2613
+ ...parseMethod(attrs[OUTCOME_ATTRIBUTE_METHOD_KEY]) !== void 0 ? { method: parseMethod(attrs[OUTCOME_ATTRIBUTE_METHOD_KEY]) } : {},
2614
+ ...event.outputSummary !== void 0 ? { actual: event.outputSummary } : {},
2615
+ ...attrs.evidence !== void 0 ? { evidence: attrs.evidence } : {},
2616
+ observedAt: Number.isFinite(observedAt) ? observedAt : Date.parse(event.timestamp)
2617
+ };
2618
+ }
2619
+ function extractOutcomesFromTraceEvents(events) {
2620
+ const out = [];
2621
+ for (const event of events) {
2622
+ if (event.event === OUTCOME_LEGACY_EVENT) {
2623
+ out.push(fromOutcomeObservedEvent(event));
2624
+ }
2625
+ }
2626
+ return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));
2627
+ }
2628
+ function extractOutcomesFromPersistedEvents(events) {
2629
+ const out = [];
2630
+ for (const event of events) {
2631
+ const outcome = fromPersistedOutcome(event);
2632
+ if (outcome) out.push(outcome);
2633
+ }
2634
+ return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));
2635
+ }
2636
+ function summarizeObservedOutcomes(outcomes) {
2637
+ const summary = {
2638
+ total: outcomes.length,
2639
+ passed: 0,
2640
+ failed: 0,
2641
+ unknown: 0,
2642
+ skipped: 0,
2643
+ outcomes: [...outcomes]
2644
+ };
2645
+ for (const outcome of outcomes) {
2646
+ summary[outcome.status] += 1;
2647
+ }
2648
+ return summary;
2649
+ }
2650
+ function outcomesMatchingStatus(outcomes, statuses) {
2651
+ const set = new Set(statuses);
2652
+ return outcomes.filter((outcome) => set.has(outcome.status));
2653
+ }
2654
+ function parseObservationFilter(value) {
2655
+ if (value === void 0 || value.trim() === "") return void 0;
2656
+ return parseObservedOutcomeStatus(value);
2657
+ }
2658
+
2659
+ // packages/core/src/outcomes/render.ts
2660
+ function renderObservedOutcomesMarkdown(summary) {
2661
+ if (summary.total === 0) {
2662
+ return "No observed outcomes recorded for this run.";
2663
+ }
2664
+ const lines = [
2665
+ `Total: ${summary.total} (passed ${summary.passed}, failed ${summary.failed}, unknown ${summary.unknown}, skipped ${summary.skipped})`,
2666
+ "",
2667
+ "| Name | Status | Expectation | Method |",
2668
+ "| --- | --- | --- | --- |"
2669
+ ];
2670
+ for (const outcome of summary.outcomes) {
2671
+ lines.push(
2672
+ `| ${outcome.name} | ${outcome.status} | ${outcome.expectation.replace(/\|/g, "\\|")} | ${outcome.method ?? "-"} |`
2673
+ );
2674
+ }
2675
+ return lines.join("\n");
2676
+ }
2677
+ function renderObservedOutcomesHtml(summary) {
2678
+ if (summary.total === 0) {
2679
+ return "<p>No observed outcomes recorded for this run.</p>";
2680
+ }
2681
+ const rows = summary.outcomes.map((outcome) => {
2682
+ const esc = (v) => v.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
2683
+ return `<tr><td>${esc(outcome.name)}</td><td>${esc(outcome.status)}</td><td>${esc(outcome.expectation)}</td><td>${esc(outcome.method ?? "-")}</td></tr>`;
2684
+ }).join("");
2685
+ return `<p>Total: ${summary.total} (passed ${summary.passed}, failed ${summary.failed}, unknown ${summary.unknown}, skipped ${summary.skipped})</p><table><thead><tr><th>Name</th><th>Status</th><th>Expectation</th><th>Method</th></tr></thead><tbody>${rows}</tbody></table>`;
2686
+ }
2687
+
2515
2688
  // packages/core/src/search.ts
2516
2689
  function parseDurationFilter(expr) {
2517
2690
  const raw = expr.trim();
@@ -2558,8 +2731,9 @@ async function searchTraces(metas, options) {
2558
2731
  }
2559
2732
  const limit = options.limit ?? 50;
2560
2733
  const sessionId = options.session?.trim();
2734
+ const observationStatus = parseObservationFilter(options.observation);
2561
2735
  const hasContentFilter = Boolean(
2562
- options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
2736
+ options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter || observationStatus
2563
2737
  );
2564
2738
  const results = [];
2565
2739
  const sessionLabel = sessionId && sessionId !== "" ? sessionId : void 0;
@@ -2604,6 +2778,22 @@ async function searchTraces(metas, options) {
2604
2778
  statusFilter: options.status
2605
2779
  });
2606
2780
  results.push(...stepMatches);
2781
+ if (observationStatus) {
2782
+ const outcomes = extractOutcomesFromTraceEvents(events);
2783
+ const matched = outcomes.filter((outcome) => outcome.status === observationStatus);
2784
+ for (const outcome of matched) {
2785
+ results.push({
2786
+ runId: m.runId,
2787
+ runName: m.name,
2788
+ runStatus: m.status,
2789
+ stepName: outcome.name,
2790
+ timestamp: outcome.observedAt,
2791
+ matchReason: `observation status=${outcome.status}`,
2792
+ matchedFields: ["outcome.status", "outcome.name"],
2793
+ filePath: m.filePath
2794
+ });
2795
+ }
2796
+ }
2607
2797
  }
2608
2798
  results.sort((a, b) => {
2609
2799
  const ta = a.timestamp ?? 0;
@@ -2780,9 +2970,10 @@ function buildActivitySummary(index, options = {}) {
2780
2970
  entries
2781
2971
  };
2782
2972
  }
2783
- function renderActivitySummaryHuman(summary) {
2973
+ function renderActivitySummaryHuman(summary, options) {
2784
2974
  const lines = [];
2785
- const todayStart = /* @__PURE__ */ new Date();
2975
+ const nowMs = options?.nowMs ?? Date.now();
2976
+ const todayStart = new Date(nowMs);
2786
2977
  todayStart.setHours(0, 0, 0, 0);
2787
2978
  const todayMs = todayStart.getTime();
2788
2979
  const today = summary.entries.filter(
@@ -3666,6 +3857,6 @@ function defaultBundleOutputPath(runIds) {
3666
3857
  return path.resolve(`agent-inspect-bundle-${label}-${stamp}`);
3667
3858
  }
3668
3859
 
3669
- export { Redactor, TraceDirectory, __commonJS, __require, __toESM, aggregateBundleSafeStatus, aggregateSessionCheckResults, applyProfileMetadataCaps, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildLocalExplanation, buildPlaceholderArtifact, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, bundleFailsOnSafety, defaultBundleOutputPath, enrichSessionRunRecord, extractCorrelationMetadata, extractMetadata, filterMetasBySessionScope, filterTraces, formatDuration2 as formatDuration, formatTimestamp, getIndent, getTraceFilePath, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadTraceMetadataList, nanoid, normalizeBundleOutputPath, parseDuration, parseDurationFilter, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderErrorLine, renderRunWhat, renderStepLine, renderTimeline, renderTraceStats, resolveBundleRunIds, resolveRedactionProfile, resolveTraceDir, searchTraces, source_default, truncateName, truncateStringForProfile, validateEvent };
3670
- //# sourceMappingURL=chunk-BS5LSKZ3.mjs.map
3671
- //# sourceMappingURL=chunk-BS5LSKZ3.mjs.map
3860
+ export { Redactor, TraceDirectory, __commonJS, __require, __toESM, aggregateBundleSafeStatus, aggregateSessionCheckResults, applyProfileMetadataCaps, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildLocalExplanation, buildPlaceholderArtifact, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, bundleFailsOnSafety, defaultBundleOutputPath, enrichSessionRunRecord, extractCorrelationMetadata, extractMetadata, extractOutcomesFromPersistedEvents, extractOutcomesFromTraceEvents, filterMetasBySessionScope, filterTraces, formatDuration2 as formatDuration, formatTimestamp, getIndent, getTraceFilePath, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadTraceMetadataList, nanoid, normalizeBundleOutputPath, outcomesMatchingStatus, parseDuration, parseDurationFilter, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderErrorLine, renderObservedOutcomesHtml, renderObservedOutcomesMarkdown, renderRunWhat, renderStepLine, renderTimeline, renderTraceStats, resolveBundleRunIds, resolveRedactionProfile, resolveTraceDir, searchTraces, source_default, summarizeObservedOutcomes, truncateName, truncateStringForProfile, validateEvent };
3861
+ //# sourceMappingURL=chunk-ORHDQUT6.mjs.map
3862
+ //# sourceMappingURL=chunk-ORHDQUT6.mjs.map