@wix/pathgrade 1.0.38 → 1.0.40
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/README.md +5 -5
- package/dist/adapters/jest/results.d.ts +1 -0
- package/dist/adapters/jest/results.js +36 -14
- package/dist/adapters/jest/runner-adapter.d.ts +1 -0
- package/dist/adapters/jest/runner-adapter.js +5 -1
- package/dist/adapters/node-test/runner-adapter.js +6 -5
- package/dist/affected/meta.d.ts +4 -1
- package/dist/affected/meta.js +9 -5
- package/dist/affected/select.js +1 -1
- package/dist/agents/claude/sdk-message-projector.js +4 -5
- package/dist/agents/claude/tool-permission-bridge.js +2 -1
- package/dist/agents/codex-app-server/item-projection.js +2 -2
- package/dist/agents/codex-app-server/mcp-approval-correlator.js +3 -2
- package/dist/agents/opencode.js +4 -5
- package/dist/commands/report.js +5 -26
- package/dist/internal/direct-mcp-v2/acp-author-projector.js +20 -7
- package/dist/reporters/cli.js +20 -1
- package/dist/reporters/github-comment.js +18 -7
- package/dist/reporters/loader.d.ts +4 -0
- package/dist/reporters/loader.js +26 -9
- package/dist/reporting/comparison-contract.d.ts +3 -2
- package/dist/reporting/comparison-contract.js +66 -33
- package/dist/reporting/core.js +35 -8
- package/dist/reporting/reliability-contract.d.ts +1 -0
- package/dist/reporting/report-parser.js +125 -5
- package/dist/reporting/source-metadata.d.ts +3 -0
- package/dist/reporting/source-metadata.js +67 -2
- package/dist/reporting/types.d.ts +5 -1
- package/dist/runners/model-builders.d.ts +1 -0
- package/dist/runners/model-builders.js +36 -12
- package/dist/runners/model.d.ts +2 -0
- package/dist/runners/orchestrator.js +3 -4
- package/dist/runners/repeated-invocation.js +2 -5
- package/dist/runners/report-projection.js +84 -0
- package/dist/runners/vitest-adapter.js +6 -2
- package/dist/sdk/agent.js +10 -1
- package/dist/sdk/evaluate.js +58 -3
- package/dist/sdk/judge-prompt-builder.js +11 -7
- package/dist/sdk/mcp-event-input.d.ts +1 -0
- package/dist/sdk/mcp-event-input.js +3 -0
- package/dist/sdk/mcp-evidence.js +16 -3
- package/dist/sdk/mcp-safety.js +2 -2
- package/dist/sdk/scorers.d.ts +5 -0
- package/dist/sdk/scorers.js +4 -0
- package/dist/sdk/scripted-mcp-events.js +3 -2
- package/dist/sdk/tool-event-log.js +18 -3
- package/dist/sdk/tool-event-secrets.d.ts +4 -0
- package/dist/sdk/tool-event-secrets.js +33 -2
- package/dist/sdk/types.d.ts +2 -0
- package/dist/tool-event-results.d.ts +3 -0
- package/dist/tool-event-results.js +153 -23
- package/dist/types.d.ts +14 -7
- package/package.json +2 -2
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectStructuredSensitiveValues, isSensitiveValueScanLimitError } from '../tool-event-results.js';
|
|
2
|
+
import { attachOriginalMcpInput, clearOriginalMcpInput, getOriginalMcpInput, } from './mcp-event-input.js';
|
|
2
3
|
const sensitiveValuesByEvent = new WeakMap();
|
|
3
4
|
export function attachToolEventSensitiveValues(event, sensitiveValues) {
|
|
4
|
-
sensitiveValuesByEvent.set(event, [...
|
|
5
|
+
sensitiveValuesByEvent.set(event, [...new Set([
|
|
6
|
+
...getToolEventSensitiveValues(event),
|
|
7
|
+
...sensitiveValues,
|
|
8
|
+
])]);
|
|
5
9
|
return event;
|
|
6
10
|
}
|
|
7
11
|
export function getToolEventSensitiveValues(event) {
|
|
8
12
|
return sensitiveValuesByEvent.get(event) ?? [];
|
|
9
13
|
}
|
|
14
|
+
export function attachLiveMcpInput(event, input) {
|
|
15
|
+
let sensitiveValues;
|
|
16
|
+
try {
|
|
17
|
+
sensitiveValues = collectStructuredSensitiveValues(input);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (!isSensitiveValueScanLimitError(error))
|
|
21
|
+
throw error;
|
|
22
|
+
return redactToolEventPayload(event);
|
|
23
|
+
}
|
|
24
|
+
return attachToolEventSensitiveValues(attachOriginalMcpInput(event, input), sensitiveValues);
|
|
25
|
+
}
|
|
26
|
+
export function redactToolEventPayload(event) {
|
|
27
|
+
return {
|
|
28
|
+
...event,
|
|
29
|
+
arguments: { redacted: true },
|
|
30
|
+
summary: `${event.action} via ${event.providerToolName}`,
|
|
31
|
+
rawSnippet: '<redacted>',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function collectToolEventSensitiveValues(events) {
|
|
35
|
+
return [...new Set(events.flatMap((event) => getToolEventSensitiveValues(event)))];
|
|
36
|
+
}
|
|
37
|
+
export function clearToolEventRuntimeMetadata(event) {
|
|
38
|
+
sensitiveValuesByEvent.delete(event);
|
|
39
|
+
clearOriginalMcpInput(event);
|
|
40
|
+
}
|
|
10
41
|
export function cloneToolEventWithRuntimeMetadata(source, overrides) {
|
|
11
42
|
const clone = attachToolEventSensitiveValues({ ...source, ...overrides }, getToolEventSensitiveValues(source));
|
|
12
43
|
const originalInput = getOriginalMcpInput(source);
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -360,6 +360,8 @@ export interface EvaluateOptions {
|
|
|
360
360
|
failFast?: boolean;
|
|
361
361
|
llm?: LLMPort;
|
|
362
362
|
onScorerError?: 'skip' | 'zero' | 'fail';
|
|
363
|
+
/** Evidence visible to deterministic scorers. Live mode is unavailable for snapshot replay. */
|
|
364
|
+
deterministicToolEvidence?: 'persisted' | 'live';
|
|
363
365
|
/** Stable identity for this evaluation definition across separate runs. */
|
|
364
366
|
evaluationDefinitionKey?: string;
|
|
365
367
|
}
|
|
@@ -7,4 +7,7 @@ export declare function collectSensitiveEnvValues(env?: Readonly<Record<string,
|
|
|
7
7
|
* is important for summaries, snippets, traces, and provider error text.
|
|
8
8
|
*/
|
|
9
9
|
export declare function sanitizePersistenceValue<T>(source: T, explicitSensitiveValues?: readonly string[]): T;
|
|
10
|
+
export declare function sanitizeUntrustedPersistenceValue<T>(source: T, explicitSensitiveValues?: readonly string[]): T;
|
|
11
|
+
export declare function isSensitiveValueScanLimitError(error: unknown): boolean;
|
|
10
12
|
export declare function sanitizeToolEventResult(source: Readonly<ToolEventResult>, sensitiveValues: readonly string[]): ToolEventResult;
|
|
13
|
+
export declare function collectStructuredSensitiveValues(source: unknown): string[];
|
|
@@ -24,6 +24,10 @@ const SECRET_KEY_NAMES = [
|
|
|
24
24
|
'connectionstring',
|
|
25
25
|
'credentials',
|
|
26
26
|
'credential',
|
|
27
|
+
'grant',
|
|
28
|
+
'capability',
|
|
29
|
+
'capabilityurl',
|
|
30
|
+
'cursor',
|
|
27
31
|
'svsession',
|
|
28
32
|
'smsession',
|
|
29
33
|
'wixsession',
|
|
@@ -32,6 +36,10 @@ const SECRET_KEY_NAMES = [
|
|
|
32
36
|
const EXACT_ONLY_SECRET_KEY_NAMES = new Set([
|
|
33
37
|
'auth',
|
|
34
38
|
'token',
|
|
39
|
+
'grant',
|
|
40
|
+
'capability',
|
|
41
|
+
'capabilityurl',
|
|
42
|
+
'cursor',
|
|
35
43
|
'svsession',
|
|
36
44
|
'smsession',
|
|
37
45
|
'wixsession',
|
|
@@ -39,6 +47,9 @@ const EXACT_ONLY_SECRET_KEY_NAMES = new Set([
|
|
|
39
47
|
]);
|
|
40
48
|
const NON_SECRET_ENVIRONMENT_KEY_NAMES = new Set(['tokencount', 'tokenizersparallelism', 'tokenusage']);
|
|
41
49
|
const BOUNDARY_ONLY_SENSITIVE_VALUE_MAX_LENGTH = 1;
|
|
50
|
+
const MAX_SANITIZE_DEPTH = 64;
|
|
51
|
+
const MAX_SENSITIVE_SCAN_NODES = 100_000;
|
|
52
|
+
const MAX_SENSITIVE_JSON_CHARS = 1024 * 1024;
|
|
42
53
|
export function collectSensitiveEnvValues(env) {
|
|
43
54
|
return [...new Set(Object.entries(env ?? {})
|
|
44
55
|
.filter((entry) => typeof entry[1] === 'string')
|
|
@@ -60,15 +71,36 @@ export function sanitizePersistenceValue(source, explicitSensitiveValues = []) {
|
|
|
60
71
|
])].sort((a, b) => b.length - a.length);
|
|
61
72
|
return sanitizeValue(source, '', sensitiveValues, new Set(explicitValues));
|
|
62
73
|
}
|
|
74
|
+
export function sanitizeUntrustedPersistenceValue(source, explicitSensitiveValues = []) {
|
|
75
|
+
try {
|
|
76
|
+
return sanitizePersistenceValue(source, explicitSensitiveValues);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (!isSensitiveValueScanLimitError(error))
|
|
80
|
+
throw error;
|
|
81
|
+
if (Array.isArray(source))
|
|
82
|
+
return [];
|
|
83
|
+
if (isRecord(source))
|
|
84
|
+
return { redacted: true };
|
|
85
|
+
return '<redacted>';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export function isSensitiveValueScanLimitError(error) {
|
|
89
|
+
return error instanceof Error && error.message.startsWith('Sensitive-value scan exceeded');
|
|
90
|
+
}
|
|
63
91
|
export function sanitizeToolEventResult(source, sensitiveValues) {
|
|
64
92
|
const result = {};
|
|
65
93
|
let truncated = source.truncated === true;
|
|
66
94
|
const addBounded = (key, value) => {
|
|
67
95
|
if (typeof value !== 'string')
|
|
68
96
|
return;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
97
|
+
const explicitValues = [...new Set(sensitiveValues.filter((entry) => entry.length > 0))];
|
|
98
|
+
const overlap = explicitValues.reduce((max, entry) => Math.max(max, entry.length), 0);
|
|
99
|
+
const prefix = value.slice(0, TOOL_RESULT_MAX_CHARS + Math.max(overlap, 1));
|
|
100
|
+
const bounded = boundText(redactSensitiveValues(prefix, explicitValues, new Set(explicitValues)));
|
|
101
|
+
const sanitized = boundText(sanitizePersistenceValue(bounded.value, sensitiveValues));
|
|
102
|
+
result[key] = sanitized.value;
|
|
103
|
+
truncated ||= value.length > prefix.length || bounded.truncated || sanitized.truncated;
|
|
72
104
|
};
|
|
73
105
|
addBounded('content', source.content);
|
|
74
106
|
addBounded('stdout', source.stdout);
|
|
@@ -96,56 +128,93 @@ function redactSensitiveValues(value, sensitiveValues, explicitSensitiveValues)
|
|
|
96
128
|
}
|
|
97
129
|
return redacted;
|
|
98
130
|
}
|
|
99
|
-
function collectStructuredSensitiveValues(source) {
|
|
131
|
+
export function collectStructuredSensitiveValues(source) {
|
|
100
132
|
const values = new Set();
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
let scannedNodes = 0;
|
|
134
|
+
let parsedJsonChars = 0;
|
|
135
|
+
const pending = [
|
|
136
|
+
{ value: source, key: '' },
|
|
137
|
+
];
|
|
138
|
+
while (pending.length > 0) {
|
|
139
|
+
if (++scannedNodes > MAX_SENSITIVE_SCAN_NODES) {
|
|
140
|
+
throw new Error('Sensitive-value scan exceeded the input node limit');
|
|
141
|
+
}
|
|
142
|
+
const { value, key } = pending.pop();
|
|
143
|
+
if (typeof value === 'string') {
|
|
144
|
+
if (value.length > 0 && !isNumericTokenTelemetry(key, value) && isSecretKey(key)) {
|
|
145
|
+
values.add(value);
|
|
146
|
+
}
|
|
147
|
+
for (const match of value.matchAll(/[?&](?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|token|secret|auth|password|passwd|session(?:id)?|cookie)=([^&#\s]+)/gi)) {
|
|
148
|
+
if (match[1])
|
|
149
|
+
values.add(match[1]);
|
|
150
|
+
}
|
|
151
|
+
for (const sensitiveValue of collectCredentialShapeSensitiveValues(value)) {
|
|
152
|
+
values.add(sensitiveValue);
|
|
153
|
+
}
|
|
154
|
+
const trimmed = value.trim();
|
|
155
|
+
const looksStructured = (trimmed.startsWith('{') && trimmed.endsWith('}'))
|
|
156
|
+
|| (trimmed.startsWith('[') && trimmed.endsWith(']'));
|
|
157
|
+
if (looksStructured && (parsedJsonChars += value.length) > MAX_SENSITIVE_JSON_CHARS) {
|
|
158
|
+
throw new Error('Sensitive-value scan exceeded the nested JSON limit');
|
|
159
|
+
}
|
|
160
|
+
const structured = looksStructured ? parseStructuredJson(value) : undefined;
|
|
161
|
+
if (structured !== undefined)
|
|
162
|
+
pending.push({ value: structured, key });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if ((typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint')
|
|
166
|
+
&& !isNumericTokenTelemetry(key, value) && isSecretKey(key)) {
|
|
167
|
+
values.add(String(value));
|
|
168
|
+
continue;
|
|
106
169
|
}
|
|
107
170
|
if (Array.isArray(value)) {
|
|
108
171
|
for (const entry of value)
|
|
109
|
-
|
|
110
|
-
|
|
172
|
+
pending.push({ value: entry, key });
|
|
173
|
+
continue;
|
|
111
174
|
}
|
|
112
175
|
if (isRecord(value)) {
|
|
113
|
-
for (const [entryKey, entryValue] of Object.entries(value))
|
|
114
|
-
|
|
176
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
177
|
+
pending.push({ value: entryValue, key: entryKey });
|
|
178
|
+
}
|
|
115
179
|
}
|
|
116
|
-
}
|
|
117
|
-
visit(source, '');
|
|
180
|
+
}
|
|
118
181
|
return [...values];
|
|
119
182
|
}
|
|
120
|
-
function sanitizeValue(value, key, sensitiveValues, explicitSensitiveValues) {
|
|
183
|
+
function sanitizeValue(value, key, sensitiveValues, explicitSensitiveValues, depth = 0) {
|
|
121
184
|
if (!isNumericTokenTelemetry(key, value) && isSecretKey(key))
|
|
122
185
|
return '<redacted>';
|
|
123
186
|
if (typeof value === 'string') {
|
|
124
|
-
return redactCredentialShapes(redactSensitiveValues(value, sensitiveValues, explicitSensitiveValues), sensitiveValues, explicitSensitiveValues);
|
|
187
|
+
return redactCredentialShapes(redactSensitiveValues(value, sensitiveValues, explicitSensitiveValues), sensitiveValues, explicitSensitiveValues, depth);
|
|
125
188
|
}
|
|
189
|
+
if (depth >= MAX_SANITIZE_DEPTH && (Array.isArray(value) || isRecord(value)))
|
|
190
|
+
return '<redacted>';
|
|
126
191
|
if (Array.isArray(value)) {
|
|
127
|
-
return value.map((entry) => sanitizeValue(entry, key, sensitiveValues, explicitSensitiveValues));
|
|
192
|
+
return value.map((entry) => sanitizeValue(entry, key, sensitiveValues, explicitSensitiveValues, depth + 1));
|
|
128
193
|
}
|
|
129
194
|
if (isRecord(value)) {
|
|
130
195
|
return Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => [
|
|
131
196
|
entryKey,
|
|
132
|
-
sanitizeValue(entryValue, entryKey, sensitiveValues, explicitSensitiveValues),
|
|
197
|
+
sanitizeValue(entryValue, entryKey, sensitiveValues, explicitSensitiveValues, depth + 1),
|
|
133
198
|
]));
|
|
134
199
|
}
|
|
135
200
|
return value;
|
|
136
201
|
}
|
|
137
|
-
function redactCredentialShapes(value, sensitiveValues, explicitSensitiveValues) {
|
|
202
|
+
function redactCredentialShapes(value, sensitiveValues, explicitSensitiveValues, depth) {
|
|
138
203
|
let redacted = value;
|
|
204
|
+
const credentialShapeValues = collectCredentialShapeSensitiveValues(redacted);
|
|
205
|
+
redacted = redactSensitiveValues(redacted, credentialShapeValues, new Set(credentialShapeValues));
|
|
139
206
|
const structured = parseStructuredJson(redacted);
|
|
140
207
|
if (structured !== undefined) {
|
|
141
208
|
const nestedSensitiveValues = [...new Set([
|
|
142
209
|
...sensitiveValues,
|
|
143
210
|
...collectStructuredSensitiveValues(structured),
|
|
144
211
|
])].sort((a, b) => b.length - a.length);
|
|
145
|
-
redacted = JSON.stringify(sanitizeValue(structured, '', nestedSensitiveValues, explicitSensitiveValues));
|
|
212
|
+
redacted = JSON.stringify(sanitizeValue(structured, '', nestedSensitiveValues, explicitSensitiveValues, depth + 1));
|
|
146
213
|
}
|
|
147
214
|
if (redacted.includes('PRIVATE KEY-----')) {
|
|
148
|
-
|
|
215
|
+
for (const block of findPrivateKeyBlocks(redacted).reverse()) {
|
|
216
|
+
redacted = `${redacted.slice(0, block.start)}<redacted>${redacted.slice(block.end)}`;
|
|
217
|
+
}
|
|
149
218
|
}
|
|
150
219
|
if (/\b(?:bearer|basic)\s/i.test(redacted)) {
|
|
151
220
|
redacted = redacted.replace(/(\b(?:bearer|basic)\s+)[^\s,;"']+/gi, '$1<redacted>');
|
|
@@ -154,10 +223,71 @@ function redactCredentialShapes(value, sensitiveValues, explicitSensitiveValues)
|
|
|
154
223
|
redacted = redacted.replace(/([a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:)[^\s/@]+(@)/gi, '$1<redacted>$2');
|
|
155
224
|
}
|
|
156
225
|
if (redacted.includes('=') || redacted.includes(':')) {
|
|
157
|
-
redacted = redacted.replace(/(\
|
|
226
|
+
redacted = redacted.replace(/((?:^|[\s{[(,;])["']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|token|secret|auth|password|passwd|session(?:id)?|cookie)["']?\s*[=:]\s*["']?)[^\s,;"'}]+/gi, '$1<redacted>');
|
|
227
|
+
redacted = redacted.replace(/((?:^|[\s{[(,;])["'](?:grant|capability|capabilityurl|cursor)["']\s*:\s*["']?)[^\s,;"'}]+/gi, '$1<redacted>');
|
|
158
228
|
}
|
|
159
229
|
return redacted;
|
|
160
230
|
}
|
|
231
|
+
function collectCredentialShapeSensitiveValues(value) {
|
|
232
|
+
const values = new Set();
|
|
233
|
+
for (const match of value.matchAll(/https?:\/\/[^\s,;"']+\/(?:cap|capability)\/[^\s,;"']+/gi)) {
|
|
234
|
+
values.add(match[0]);
|
|
235
|
+
}
|
|
236
|
+
if (value.includes('PRIVATE KEY-----')) {
|
|
237
|
+
for (const block of findPrivateKeyBlocks(value)) {
|
|
238
|
+
values.add(value.slice(block.start, block.end));
|
|
239
|
+
if (block.body)
|
|
240
|
+
values.add(block.body);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (/\b(?:bearer|basic)\s/i.test(value)) {
|
|
244
|
+
for (const match of value.matchAll(/\b(?:bearer|basic)\s+([^\s,;"']+)/gi)) {
|
|
245
|
+
if (match[1])
|
|
246
|
+
values.add(match[1]);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (value.includes('://')) {
|
|
250
|
+
for (const match of value.matchAll(/[a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:([^\s/@]+)@/gi)) {
|
|
251
|
+
if (match[1])
|
|
252
|
+
values.add(match[1]);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (value.includes('=') || value.includes(':')) {
|
|
256
|
+
for (const match of value.matchAll(/(?:^|[\s{[(,;])["']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|token|secret|auth|password|passwd|session(?:id)?|cookie)["']?\s*[=:]\s*["']?([^\s,;"'}]+)/gi)) {
|
|
257
|
+
if (match[1])
|
|
258
|
+
values.add(match[1]);
|
|
259
|
+
}
|
|
260
|
+
for (const match of value.matchAll(/(?:^|[\s{[(,;])["'](?:grant|capability|capabilityurl|cursor)["']\s*:\s*["']?([^\s,;"'}]+)/gi)) {
|
|
261
|
+
if (match[1])
|
|
262
|
+
values.add(match[1]);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return [...values].sort((a, b) => b.length - a.length);
|
|
266
|
+
}
|
|
267
|
+
function findPrivateKeyBlocks(value) {
|
|
268
|
+
const blocks = [];
|
|
269
|
+
let open;
|
|
270
|
+
let cursor = 0;
|
|
271
|
+
while (cursor < value.length) {
|
|
272
|
+
const start = value.indexOf('-----', cursor);
|
|
273
|
+
if (start < 0)
|
|
274
|
+
break;
|
|
275
|
+
const end = value.indexOf('-----', start + 5);
|
|
276
|
+
if (end < 0)
|
|
277
|
+
break;
|
|
278
|
+
const markerEnd = end + 5;
|
|
279
|
+
const marker = value.slice(start, markerEnd);
|
|
280
|
+
if (!open && marker.startsWith('-----BEGIN ') && marker.endsWith('PRIVATE KEY-----')) {
|
|
281
|
+
open = { start, bodyStart: markerEnd };
|
|
282
|
+
}
|
|
283
|
+
else if (open && marker.startsWith('-----END ') && marker.endsWith('PRIVATE KEY-----')) {
|
|
284
|
+
blocks.push({ start: open.start, end: markerEnd, body: value.slice(open.bodyStart, start).trim() });
|
|
285
|
+
open = undefined;
|
|
286
|
+
}
|
|
287
|
+
cursor = markerEnd;
|
|
288
|
+
}
|
|
289
|
+
return blocks;
|
|
290
|
+
}
|
|
161
291
|
function isSecretKey(key) {
|
|
162
292
|
const normalized = key.replace(/[^a-z0-9]/gi, '').toLowerCase();
|
|
163
293
|
if (normalized === 'tokens')
|
package/dist/types.d.ts
CHANGED
|
@@ -185,6 +185,10 @@ export interface EvalReport {
|
|
|
185
185
|
task: string;
|
|
186
186
|
/** Canonical status for this report or consolidated group when available. */
|
|
187
187
|
status?: 'pass' | 'fail';
|
|
188
|
+
/** Whether every reportable runner attempt passed. */
|
|
189
|
+
runner_status?: 'pass' | 'fail';
|
|
190
|
+
/** Whether mean reward meets the configured threshold. */
|
|
191
|
+
threshold_status?: 'pass' | 'fail' | 'not_configured';
|
|
188
192
|
/** Schema-v2 canonical average score. */
|
|
189
193
|
mean_reward?: number;
|
|
190
194
|
/** Binary success frequency, absent when attempts are ineligible. */
|
|
@@ -203,7 +207,7 @@ export interface EvalReport {
|
|
|
203
207
|
skills_used: string[];
|
|
204
208
|
}
|
|
205
209
|
export type ComparisonUnavailableReason = 'definition_metadata_missing' | 'scorer_metadata_missing' | 'runtime_metadata_missing' | 'sampling_incomplete';
|
|
206
|
-
export interface
|
|
210
|
+
export interface ComparisonContractV1 {
|
|
207
211
|
version: 1;
|
|
208
212
|
definition_revision?: string;
|
|
209
213
|
scorer_revision?: string;
|
|
@@ -212,6 +216,7 @@ export interface ComparisonContract {
|
|
|
212
216
|
report_schema_revision: 'pathgrade-results-v2';
|
|
213
217
|
unavailable_reasons?: ComparisonUnavailableReason[];
|
|
214
218
|
}
|
|
219
|
+
export type ComparisonContract = ComparisonContractV1 | import('./reporting/reliability-contract.js').ComparisonContractV2;
|
|
215
220
|
/**
|
|
216
221
|
* TrialResult with large trace fields stripped. These fields
|
|
217
222
|
* live only in the per-group trace files; the consolidated results.json keeps
|
|
@@ -256,7 +261,7 @@ export interface PathgradeSelectionReport {
|
|
|
256
261
|
* external consumers can gate on schema revisions.
|
|
257
262
|
*/
|
|
258
263
|
export interface PathgradeReport {
|
|
259
|
-
version: 1 | 2;
|
|
264
|
+
version: 1 | 2 | 3;
|
|
260
265
|
timestamp: string;
|
|
261
266
|
/** `ci.threshold` from Pathgrade config or legacy plugin config, if configured. */
|
|
262
267
|
threshold?: number;
|
|
@@ -266,15 +271,17 @@ export interface PathgradeReport {
|
|
|
266
271
|
overall_mean_reward?: number;
|
|
267
272
|
attempts_requested?: number;
|
|
268
273
|
attempts_completed?: number;
|
|
269
|
-
/**
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
/** Whether every reportable runner attempt passed. */
|
|
275
|
+
runner_status?: 'pass' | 'fail';
|
|
276
|
+
/** Whether overall mean reward meets the configured threshold. */
|
|
277
|
+
threshold_status?: 'pass' | 'fail' | 'not_configured';
|
|
278
|
+
/** Conjunction of runner assertions and the optional aggregate threshold. */
|
|
274
279
|
status: 'pass' | 'fail';
|
|
275
280
|
/** Agent Evals compatibility manifest when changed selection finds no runnable evals. */
|
|
276
281
|
run_kind?: 'evaluation' | 'no-affected';
|
|
277
282
|
groups: PathgradeGroupReport[];
|
|
283
|
+
/** Current selected-task accounting, required for schema-v3 reports. */
|
|
284
|
+
task_inventory?: import('./reporting/reliability-contract.js').TaskInventory;
|
|
278
285
|
/**
|
|
279
286
|
* Present when `pathgrade run --changed` produced the run. Absent on
|
|
280
287
|
* plain `pathgrade run`. Backward compatible — older consumers ignore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/pathgrade",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"packageManager": "yarn@4.12.0",
|
|
5
5
|
"description": "Evaluate whether AI agents discover and use your skills correctly",
|
|
6
6
|
"exports": {
|
|
@@ -142,5 +142,5 @@
|
|
|
142
142
|
"typescript": "^5.9.3",
|
|
143
143
|
"zod": "4.3.6"
|
|
144
144
|
},
|
|
145
|
-
"falconPackageHash": "
|
|
145
|
+
"falconPackageHash": "4c4d43a7c8d439f02756404accbc72b44db02c52db4d0c2b2d18452f"
|
|
146
146
|
}
|