@cat-factory/contracts 0.261.1 → 0.263.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.
- package/dist/documents.d.ts +24 -0
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +19 -6
- package/dist/documents.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pr-report.d.ts +29 -1
- package/dist/pr-report.d.ts.map +1 -1
- package/dist/pr-report.js +15 -1
- package/dist/pr-report.js.map +1 -1
- package/dist/reserved-env-keys.d.ts.map +1 -1
- package/dist/reserved-env-keys.js +5 -0
- package/dist/reserved-env-keys.js.map +1 -1
- package/dist/routes/_shared.d.ts +16 -0
- package/dist/routes/_shared.d.ts.map +1 -1
- package/dist/routes/_shared.js +15 -0
- package/dist/routes/_shared.js.map +1 -1
- package/dist/routes/debug-api.d.ts +18 -0
- package/dist/routes/debug-api.d.ts.map +1 -1
- package/dist/routes/debug-api.js +19 -19
- package/dist/routes/debug-api.js.map +1 -1
- package/dist/routes/notification-webhooks.d.ts +6 -0
- package/dist/routes/notification-webhooks.d.ts.map +1 -1
- package/dist/routes/notification-webhooks.js +7 -7
- package/dist/routes/notification-webhooks.js.map +1 -1
- package/dist/routes/public-api.d.ts +48 -0
- package/dist/routes/public-api.d.ts.map +1 -1
- package/dist/routes/public-api.js +50 -50
- package/dist/routes/public-api.js.map +1 -1
- package/dist/routes/public-decisions.d.ts +82 -0
- package/dist/routes/public-decisions.d.ts.map +1 -1
- package/dist/routes/public-decisions.js +83 -83
- package/dist/routes/public-decisions.js.map +1 -1
- package/dist/routes/public-evidence.d.ts +125 -0
- package/dist/routes/public-evidence.d.ts.map +1 -1
- package/dist/routes/public-evidence.js +26 -5
- package/dist/routes/public-evidence.js.map +1 -1
- package/dist/routes/spec.d.ts +84 -0
- package/dist/routes/spec.d.ts.map +1 -1
- package/dist/routes/spec.js +15 -0
- package/dist/routes/spec.js.map +1 -1
- package/dist/run-evidence.d.ts +152 -0
- package/dist/run-evidence.d.ts.map +1 -0
- package/dist/run-evidence.js +192 -0
- package/dist/run-evidence.js.map +1 -0
- package/dist/run-outcome.d.ts +370 -0
- package/dist/run-outcome.d.ts.map +1 -0
- package/dist/run-outcome.js +540 -0
- package/dist/run-outcome.js.map +1 -0
- package/package.json +1 -1
|
@@ -171,6 +171,7 @@ export declare const getPublicRunReportContract: {
|
|
|
171
171
|
readonly notCovered: import("valibot").NumberSchema<undefined>;
|
|
172
172
|
readonly regressions: import("valibot").NumberSchema<undefined>;
|
|
173
173
|
readonly total: import("valibot").NumberSchema<undefined>;
|
|
174
|
+
readonly unmatchedVerdicts: import("valibot").OptionalSchema<import("valibot").NumberSchema<undefined>, undefined>;
|
|
174
175
|
}, undefined>;
|
|
175
176
|
readonly environments: import("valibot").ObjectSchema<{
|
|
176
177
|
readonly status: import("valibot").PicklistSchema<["reported", "absent"], undefined>;
|
|
@@ -256,6 +257,128 @@ export declare const getPublicRunReportContract: {
|
|
|
256
257
|
readonly truncations: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
257
258
|
}, undefined>;
|
|
258
259
|
};
|
|
260
|
+
} & {
|
|
261
|
+
readonly minScope: "read";
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* The run's OUTCOME summary: what it changed and what backs that up, for a reader who will not
|
|
265
|
+
* open the diff.
|
|
266
|
+
*
|
|
267
|
+
* The sibling of the report above rather than a projection of it, and the difference is the
|
|
268
|
+
* AUDIENCE, not the facts: the report is a reviewer's evidence bundle (every failing check by
|
|
269
|
+
* name, every captured log tail, the merge assessment), this is the product-language answer the
|
|
270
|
+
* app's outcome card renders, and the counts underneath both are computed by the same shared
|
|
271
|
+
* rules. A consumer deciding whether a change is acceptable wants the report; one reporting to a
|
|
272
|
+
* person what shipped wants this.
|
|
273
|
+
*
|
|
274
|
+
* Deliberately not derived from the report on the wire: the report is BOUNDED to what fits in a
|
|
275
|
+
* pull-request body, and a tally taken off its capped tables would be quietly wrong.
|
|
276
|
+
*/
|
|
277
|
+
export declare const getPublicRunOutcomeContract: {
|
|
278
|
+
readonly method: "get";
|
|
279
|
+
readonly requestPathParamsSchema: import("valibot").ObjectSchema<{
|
|
280
|
+
runId: import("valibot").StringSchema<undefined>;
|
|
281
|
+
}, undefined> & import("@toad-contracts/core").StandardObjectKeysV1<unknown, unknown>;
|
|
282
|
+
readonly pathResolver: ({ runId }: {
|
|
283
|
+
runId: string;
|
|
284
|
+
}) => string;
|
|
285
|
+
readonly responsesByStatusCode: {
|
|
286
|
+
readonly '4xx': import("valibot").ObjectSchema<{
|
|
287
|
+
readonly error: import("valibot").ObjectSchema<{
|
|
288
|
+
readonly code: import("valibot").StringSchema<undefined>;
|
|
289
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
290
|
+
readonly details: import("valibot").OptionalSchema<import("valibot").UnknownSchema, undefined>;
|
|
291
|
+
readonly issues: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
292
|
+
readonly path: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
293
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
294
|
+
}, undefined>, undefined>, undefined>;
|
|
295
|
+
}, undefined>;
|
|
296
|
+
}, undefined>;
|
|
297
|
+
readonly '5xx': import("valibot").ObjectSchema<{
|
|
298
|
+
readonly error: import("valibot").ObjectSchema<{
|
|
299
|
+
readonly code: import("valibot").StringSchema<undefined>;
|
|
300
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
301
|
+
readonly details: import("valibot").OptionalSchema<import("valibot").UnknownSchema, undefined>;
|
|
302
|
+
readonly issues: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
303
|
+
readonly path: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
304
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
305
|
+
}, undefined>, undefined>, undefined>;
|
|
306
|
+
}, undefined>;
|
|
307
|
+
}, undefined>;
|
|
308
|
+
readonly 200: import("valibot").ObjectSchema<{
|
|
309
|
+
readonly version: import("valibot").NumberSchema<undefined>;
|
|
310
|
+
readonly disposition: import("valibot").PicklistSchema<["merged", "awaiting_merge", "in_flight", "needs_attention", "not_run", "unknown"], undefined>;
|
|
311
|
+
readonly title: import("valibot").StringSchema<undefined>;
|
|
312
|
+
readonly ask: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
313
|
+
readonly pullRequests: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
314
|
+
readonly url: import("valibot").StringSchema<undefined>;
|
|
315
|
+
readonly number: import("valibot").NullableSchema<import("valibot").NumberSchema<undefined>, undefined>;
|
|
316
|
+
readonly branch: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
317
|
+
readonly repo: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
318
|
+
}, undefined>, undefined>;
|
|
319
|
+
readonly requirements: import("valibot").VariantSchema<"status", [import("valibot").ObjectSchema<{
|
|
320
|
+
readonly status: import("valibot").LiteralSchema<"absent", undefined>;
|
|
321
|
+
readonly gap: import("valibot").PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported", "no_verdicts", "no_requirements"], undefined>;
|
|
322
|
+
}, undefined>, import("valibot").ObjectSchema<{
|
|
323
|
+
readonly status: import("valibot").LiteralSchema<"reported", undefined>;
|
|
324
|
+
readonly spec: import("valibot").PicklistSchema<["joined", "not_read"], undefined>;
|
|
325
|
+
readonly met: import("valibot").NumberSchema<undefined>;
|
|
326
|
+
readonly notMet: import("valibot").NumberSchema<undefined>;
|
|
327
|
+
readonly notCovered: import("valibot").NumberSchema<undefined>;
|
|
328
|
+
readonly regressions: import("valibot").NumberSchema<undefined>;
|
|
329
|
+
readonly total: import("valibot").NumberSchema<undefined>;
|
|
330
|
+
readonly unmatchedVerdicts: import("valibot").NumberSchema<undefined>;
|
|
331
|
+
readonly entries: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
332
|
+
readonly id: import("valibot").StringSchema<undefined>;
|
|
333
|
+
readonly title: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
334
|
+
readonly verdict: import("valibot").PicklistSchema<["met", "not_met", "not_covered"], undefined>;
|
|
335
|
+
readonly detail: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
336
|
+
readonly state: import("valibot").NullableSchema<import("valibot").PicklistSchema<["aspirational", "established"], undefined>, undefined>;
|
|
337
|
+
readonly regression: import("valibot").BooleanSchema<undefined>;
|
|
338
|
+
}, undefined>, undefined>;
|
|
339
|
+
}, undefined>], undefined>;
|
|
340
|
+
readonly tests: import("valibot").VariantSchema<"status", [import("valibot").ObjectSchema<{
|
|
341
|
+
readonly status: import("valibot").LiteralSchema<"absent", undefined>;
|
|
342
|
+
readonly gap: import("valibot").PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported"], undefined>;
|
|
343
|
+
}, undefined>, import("valibot").ObjectSchema<{
|
|
344
|
+
readonly status: import("valibot").LiteralSchema<"reported", undefined>;
|
|
345
|
+
readonly verdict: import("valibot").PicklistSchema<["greenlit", "concerns", "could_not_run"], undefined>;
|
|
346
|
+
readonly summary: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
347
|
+
readonly abortReason: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
348
|
+
readonly areas: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
349
|
+
readonly passed: import("valibot").NumberSchema<undefined>;
|
|
350
|
+
readonly failed: import("valibot").NumberSchema<undefined>;
|
|
351
|
+
readonly skipped: import("valibot").NumberSchema<undefined>;
|
|
352
|
+
readonly concerns: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
353
|
+
readonly title: import("valibot").StringSchema<undefined>;
|
|
354
|
+
readonly severity: import("valibot").PicklistSchema<["low", "medium", "high", "critical"], undefined>;
|
|
355
|
+
}, undefined>, undefined>;
|
|
356
|
+
readonly environment: import("valibot").NullableSchema<import("valibot").PicklistSchema<["local", "ephemeral"], undefined>, undefined>;
|
|
357
|
+
}, undefined>], undefined>;
|
|
358
|
+
readonly visuals: import("valibot").VariantSchema<"status", [import("valibot").ObjectSchema<{
|
|
359
|
+
readonly status: import("valibot").LiteralSchema<"absent", undefined>;
|
|
360
|
+
readonly gap: import("valibot").PicklistSchema<["run_unavailable", "no_visual_step", "none_captured"], undefined>;
|
|
361
|
+
readonly detail: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
362
|
+
}, undefined>, import("valibot").ObjectSchema<{
|
|
363
|
+
readonly status: import("valibot").LiteralSchema<"reported", undefined>;
|
|
364
|
+
readonly source: import("valibot").PicklistSchema<["visual_confirm", "tester"], undefined>;
|
|
365
|
+
readonly phase: import("valibot").NullableSchema<import("valibot").PicklistSchema<["awaiting_human", "fixing", "approved"], undefined>, undefined>;
|
|
366
|
+
readonly views: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
367
|
+
readonly view: import("valibot").StringSchema<undefined>;
|
|
368
|
+
readonly artifactId: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
369
|
+
readonly referenceArtifactId: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
370
|
+
}, undefined>, undefined>;
|
|
371
|
+
}, undefined>], undefined>;
|
|
372
|
+
readonly checks: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
373
|
+
readonly kind: import("valibot").PicklistSchema<["ci", "validation", "reproduction"], undefined>;
|
|
374
|
+
readonly state: import("valibot").PicklistSchema<["pass", "fail", "pending", "inconclusive"], undefined>;
|
|
375
|
+
readonly reproduction: import("valibot").NullableSchema<import("valibot").PicklistSchema<["reproduced", "inconclusive", "declared_infeasible"], undefined>, undefined>;
|
|
376
|
+
}, undefined>, undefined>;
|
|
377
|
+
readonly truncations: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
378
|
+
}, undefined>;
|
|
379
|
+
};
|
|
380
|
+
} & {
|
|
381
|
+
readonly minScope: "read";
|
|
259
382
|
};
|
|
260
383
|
/** The binary artifacts the run captured (metadata; the bytes are a second, per-artifact fetch). */
|
|
261
384
|
export declare const listPublicRunArtifactsContract: {
|
|
@@ -301,5 +424,7 @@ export declare const listPublicRunArtifactsContract: {
|
|
|
301
424
|
}, undefined>, undefined>;
|
|
302
425
|
}, undefined>;
|
|
303
426
|
};
|
|
427
|
+
} & {
|
|
428
|
+
readonly minScope: "read";
|
|
304
429
|
};
|
|
305
430
|
//# sourceMappingURL=public-evidence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-evidence.d.ts","sourceRoot":"","sources":["../../src/routes/public-evidence.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"public-evidence.d.ts","sourceRoot":"","sources":["../../src/routes/public-evidence.ts"],"names":[],"mappings":"AAyBA;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQtC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQvC,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQ1C,CAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { defineApiContract } from '@toad-contracts/valibot';
|
|
2
2
|
import { prVerificationReportSchema } from '../pr-report.js';
|
|
3
3
|
import { publicRunArtifactListSchema } from '../public-evidence.js';
|
|
4
|
-
import {
|
|
4
|
+
import { runOutcomeSchema } from '../run-outcome.js';
|
|
5
|
+
import { errorResponses, singleStringParam, withMinScope } from './_shared.js';
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
// Route contracts for the public run-EVIDENCE surface: absolute `/api/v1` paths,
|
|
7
8
|
// authenticated in-controller by a public-API key at `read` scope. The wire shapes and the
|
|
@@ -26,17 +27,37 @@ const runIdParams = singleStringParam('runId');
|
|
|
26
27
|
* A consumer that scraped the fenced JSON block out of a PR body can read it here instead, and
|
|
27
28
|
* gets it for the runs that never opened a pull request at all.
|
|
28
29
|
*/
|
|
29
|
-
export const getPublicRunReportContract = defineApiContract({
|
|
30
|
+
export const getPublicRunReportContract = withMinScope('read', defineApiContract({
|
|
30
31
|
method: 'get',
|
|
31
32
|
requestPathParamsSchema: runIdParams,
|
|
32
33
|
pathResolver: ({ runId }) => `/api/v1/runs/${runId}/report`,
|
|
33
34
|
responsesByStatusCode: { 200: prVerificationReportSchema, ...errorResponses },
|
|
34
|
-
});
|
|
35
|
+
}));
|
|
36
|
+
/**
|
|
37
|
+
* The run's OUTCOME summary: what it changed and what backs that up, for a reader who will not
|
|
38
|
+
* open the diff.
|
|
39
|
+
*
|
|
40
|
+
* The sibling of the report above rather than a projection of it, and the difference is the
|
|
41
|
+
* AUDIENCE, not the facts: the report is a reviewer's evidence bundle (every failing check by
|
|
42
|
+
* name, every captured log tail, the merge assessment), this is the product-language answer the
|
|
43
|
+
* app's outcome card renders, and the counts underneath both are computed by the same shared
|
|
44
|
+
* rules. A consumer deciding whether a change is acceptable wants the report; one reporting to a
|
|
45
|
+
* person what shipped wants this.
|
|
46
|
+
*
|
|
47
|
+
* Deliberately not derived from the report on the wire: the report is BOUNDED to what fits in a
|
|
48
|
+
* pull-request body, and a tally taken off its capped tables would be quietly wrong.
|
|
49
|
+
*/
|
|
50
|
+
export const getPublicRunOutcomeContract = withMinScope('read', defineApiContract({
|
|
51
|
+
method: 'get',
|
|
52
|
+
requestPathParamsSchema: runIdParams,
|
|
53
|
+
pathResolver: ({ runId }) => `/api/v1/runs/${runId}/outcome`,
|
|
54
|
+
responsesByStatusCode: { 200: runOutcomeSchema, ...errorResponses },
|
|
55
|
+
}));
|
|
35
56
|
/** The binary artifacts the run captured (metadata; the bytes are a second, per-artifact fetch). */
|
|
36
|
-
export const listPublicRunArtifactsContract = defineApiContract({
|
|
57
|
+
export const listPublicRunArtifactsContract = withMinScope('read', defineApiContract({
|
|
37
58
|
method: 'get',
|
|
38
59
|
requestPathParamsSchema: runIdParams,
|
|
39
60
|
pathResolver: ({ runId }) => `/api/v1/runs/${runId}/artifacts`,
|
|
40
61
|
responsesByStatusCode: { 200: publicRunArtifactListSchema, ...errorResponses },
|
|
41
|
-
});
|
|
62
|
+
}));
|
|
42
63
|
//# sourceMappingURL=public-evidence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-evidence.js","sourceRoot":"","sources":["../../src/routes/public-evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"public-evidence.js","sourceRoot":"","sources":["../../src/routes/public-evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE9E,8EAA8E;AAC9E,iFAAiF;AACjF,2FAA2F;AAC3F,yDAAyD;AACzD,EAAE;AACF,6FAA6F;AAC7F,6FAA6F;AAC7F,+FAA+F;AAC/F,gGAAgG;AAChG,0FAA0F;AAC1F,yEAAyE;AACzE,EAAE;AACF,4FAA4F;AAC5F,2FAA2F;AAC3F,gFAAgF;AAChF,8EAA8E;AAE9E,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAY,CACpD,MAAM,EACN,iBAAiB,CAAC;IAChB,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,WAAW;IACpC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,gBAAgB,KAAK,SAAS;IAC3D,qBAAqB,EAAE,EAAE,GAAG,EAAE,0BAA0B,EAAE,GAAG,cAAc,EAAE;CAC9E,CAAC,CACH,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,YAAY,CACrD,MAAM,EACN,iBAAiB,CAAC;IAChB,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,WAAW;IACpC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,gBAAgB,KAAK,UAAU;IAC5D,qBAAqB,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,cAAc,EAAE;CACpE,CAAC,CACH,CAAA;AAED,oGAAoG;AACpG,MAAM,CAAC,MAAM,8BAA8B,GAAG,YAAY,CACxD,MAAM,EACN,iBAAiB,CAAC;IAChB,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,WAAW;IACpC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,gBAAgB,KAAK,YAAY;IAC9D,qBAAqB,EAAE,EAAE,GAAG,EAAE,2BAA2B,EAAE,GAAG,cAAc,EAAE;CAC/E,CAAC,CACH,CAAA"}
|
package/dist/routes/spec.d.ts
CHANGED
|
@@ -73,4 +73,88 @@ export declare const getServiceSpecContract: {
|
|
|
73
73
|
}, undefined>;
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* The spec as ONE RUN was judged against it, read from the branch that run pushed its work to.
|
|
78
|
+
*
|
|
79
|
+
* A sibling of {@link getServiceSpecContract} rather than a flag on it, because the two answer
|
|
80
|
+
* different questions: "what does this service require" (the default branch, the inspector's
|
|
81
|
+
* requirements window) and "what did this run rule on" (the run's branch, the outcome card). The
|
|
82
|
+
* SPA's outcome card asked the first and used the answer for the second, so while a pull request
|
|
83
|
+
* was open every verdict against a requirement the run itself added landed as "not checked".
|
|
84
|
+
*/
|
|
85
|
+
export declare const getRunSpecContract: {
|
|
86
|
+
readonly method: "get";
|
|
87
|
+
readonly requestPathParamsSchema: import("valibot").ObjectSchema<{
|
|
88
|
+
executionId: import("valibot").StringSchema<undefined>;
|
|
89
|
+
}, undefined> & import("@toad-contracts/core").StandardObjectKeysV1<unknown, unknown>;
|
|
90
|
+
readonly pathResolver: ({ executionId }: {
|
|
91
|
+
executionId: string;
|
|
92
|
+
}) => string;
|
|
93
|
+
readonly responsesByStatusCode: {
|
|
94
|
+
readonly '4xx': import("valibot").ObjectSchema<{
|
|
95
|
+
readonly error: import("valibot").ObjectSchema<{
|
|
96
|
+
readonly code: import("valibot").StringSchema<undefined>;
|
|
97
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
98
|
+
readonly details: import("valibot").OptionalSchema<import("valibot").UnknownSchema, undefined>;
|
|
99
|
+
readonly issues: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
100
|
+
readonly path: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
101
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
102
|
+
}, undefined>, undefined>, undefined>;
|
|
103
|
+
}, undefined>;
|
|
104
|
+
}, undefined>;
|
|
105
|
+
readonly '5xx': import("valibot").ObjectSchema<{
|
|
106
|
+
readonly error: import("valibot").ObjectSchema<{
|
|
107
|
+
readonly code: import("valibot").StringSchema<undefined>;
|
|
108
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
109
|
+
readonly details: import("valibot").OptionalSchema<import("valibot").UnknownSchema, undefined>;
|
|
110
|
+
readonly issues: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
111
|
+
readonly path: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
112
|
+
readonly message: import("valibot").StringSchema<undefined>;
|
|
113
|
+
}, undefined>, undefined>, undefined>;
|
|
114
|
+
}, undefined>;
|
|
115
|
+
}, undefined>;
|
|
116
|
+
readonly 200: import("valibot").ObjectSchema<{
|
|
117
|
+
readonly present: import("valibot").BooleanSchema<undefined>;
|
|
118
|
+
readonly spec: import("valibot").NullableSchema<import("valibot").ObjectSchema<{
|
|
119
|
+
readonly service: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>]>;
|
|
120
|
+
readonly summary: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
121
|
+
readonly modules: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
122
|
+
readonly name: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>]>;
|
|
123
|
+
readonly summary: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
124
|
+
readonly groups: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
125
|
+
readonly name: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>]>;
|
|
126
|
+
readonly summary: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
127
|
+
readonly requirements: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
128
|
+
readonly id: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 200, undefined>]>;
|
|
129
|
+
readonly title: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>]>;
|
|
130
|
+
readonly statement: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 4000, undefined>]>;
|
|
131
|
+
readonly kind: import("valibot").PicklistSchema<["functional", "nonfunctional", "constraint"], undefined>;
|
|
132
|
+
readonly priority: import("valibot").PicklistSchema<["must", "should", "could"], undefined>;
|
|
133
|
+
readonly state: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["aspirational", "established"], undefined>, "aspirational">;
|
|
134
|
+
readonly sourceBlockIds: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
135
|
+
readonly acceptance: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
136
|
+
readonly id: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 200, undefined>]>;
|
|
137
|
+
readonly given: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>;
|
|
138
|
+
readonly when: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>;
|
|
139
|
+
readonly outcome: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>;
|
|
140
|
+
}, undefined>, undefined>, readonly []>;
|
|
141
|
+
}, undefined>, undefined>, readonly []>;
|
|
142
|
+
readonly rules: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
143
|
+
readonly id: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 200, undefined>]>;
|
|
144
|
+
readonly rule: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 4000, undefined>]>;
|
|
145
|
+
readonly rationale: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
146
|
+
readonly sourceBlockIds: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").TrimAction, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
147
|
+
}, undefined>, undefined>, readonly []>;
|
|
148
|
+
}, undefined>, undefined>, readonly []>;
|
|
149
|
+
}, undefined>, undefined>, readonly []>;
|
|
150
|
+
}, undefined>, undefined>;
|
|
151
|
+
readonly features: import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
152
|
+
readonly module: import("valibot").StringSchema<undefined>;
|
|
153
|
+
readonly group: import("valibot").StringSchema<undefined>;
|
|
154
|
+
readonly path: import("valibot").StringSchema<undefined>;
|
|
155
|
+
readonly content: import("valibot").StringSchema<undefined>;
|
|
156
|
+
}, undefined>, undefined>;
|
|
157
|
+
}, undefined>;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
76
160
|
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/routes/spec.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKjC,CAAA"}
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/routes/spec.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKjC,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAK7B,CAAA"}
|
package/dist/routes/spec.js
CHANGED
|
@@ -13,4 +13,19 @@ export const getServiceSpecContract = defineApiContract({
|
|
|
13
13
|
pathResolver: ({ blockId }) => `/blocks/${blockId}/spec`,
|
|
14
14
|
responsesByStatusCode: { 200: serviceSpecViewSchema, ...errorResponses },
|
|
15
15
|
});
|
|
16
|
+
/**
|
|
17
|
+
* The spec as ONE RUN was judged against it, read from the branch that run pushed its work to.
|
|
18
|
+
*
|
|
19
|
+
* A sibling of {@link getServiceSpecContract} rather than a flag on it, because the two answer
|
|
20
|
+
* different questions: "what does this service require" (the default branch, the inspector's
|
|
21
|
+
* requirements window) and "what did this run rule on" (the run's branch, the outcome card). The
|
|
22
|
+
* SPA's outcome card asked the first and used the answer for the second, so while a pull request
|
|
23
|
+
* was open every verdict against a requirement the run itself added landed as "not checked".
|
|
24
|
+
*/
|
|
25
|
+
export const getRunSpecContract = defineApiContract({
|
|
26
|
+
method: 'get',
|
|
27
|
+
requestPathParamsSchema: singleStringParam('executionId'),
|
|
28
|
+
pathResolver: ({ executionId }) => `/executions/${executionId}/spec`,
|
|
29
|
+
responsesByStatusCode: { 200: serviceSpecViewSchema, ...errorResponses },
|
|
30
|
+
});
|
|
16
31
|
//# sourceMappingURL=spec.js.map
|
package/dist/routes/spec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/routes/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhE,8EAA8E;AAC9E,iEAAiE;AACjE,kFAAkF;AAClF,4EAA4E;AAC5E,mDAAmD;AACnD,8EAA8E;AAE9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;IACtD,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,iBAAiB,CAAC,SAAS,CAAC;IACrD,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,WAAW,OAAO,OAAO;IACxD,qBAAqB,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAE,GAAG,cAAc,EAAE;CACzE,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/routes/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhE,8EAA8E;AAC9E,iEAAiE;AACjE,kFAAkF;AAClF,4EAA4E;AAC5E,mDAAmD;AACnD,8EAA8E;AAE9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;IACtD,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,iBAAiB,CAAC,SAAS,CAAC;IACrD,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,WAAW,OAAO,OAAO;IACxD,qBAAqB,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAE,GAAG,cAAc,EAAE;CACzE,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;IAClD,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,iBAAiB,CAAC,aAAa,CAAC;IACzD,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,eAAe,WAAW,OAAO;IACpE,qBAAqB,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAE,GAAG,cAAc,EAAE;CACzE,CAAC,CAAA"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Block } from './entities.js';
|
|
2
|
+
import type { PipelineStep } from './execution.js';
|
|
3
|
+
import type { RequirementPriority, RequirementState, SpecDoc } from './spec.js';
|
|
4
|
+
import type { RequirementVerdict, RequirementVerdictStatus, TestReport } from './testing.js';
|
|
5
|
+
/** The API tester gate's agent kind. */
|
|
6
|
+
export declare const TESTER_AGENT_KIND = "tester-api";
|
|
7
|
+
/**
|
|
8
|
+
* Whether an agent kind is one of the tester gate kinds (API or UI).
|
|
9
|
+
*
|
|
10
|
+
* Here rather than in each consumer because every reduction of a run's test evidence starts by
|
|
11
|
+
* answering it, and the two copies that preceded this one spelled the kinds out as literals on
|
|
12
|
+
* one side and as constants on the other.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTesterKind(kind: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The step a section should report on: the LAST matching step that carries evidence, else the
|
|
17
|
+
* first matching step.
|
|
18
|
+
*
|
|
19
|
+
* Last-with-evidence, not first-match: a pipeline may legitimately carry the same kind twice (a
|
|
20
|
+
* `ci` gate after the coder and another after the tester), and the later run describes the head
|
|
21
|
+
* as it stands now. Falling back to the first match rather than to nothing is what lets a
|
|
22
|
+
* consumer tell "this pipeline has no such step" from "it has one and it has not reported yet",
|
|
23
|
+
* which are opposite facts that a single `null` states identically.
|
|
24
|
+
*/
|
|
25
|
+
export declare function selectEvidenceStep(steps: readonly PipelineStep[], matches: (step: PipelineStep) => boolean, hasEvidence: (step: PipelineStep) => boolean): PipelineStep | undefined;
|
|
26
|
+
/** Every tester step of a run, in pipeline order. */
|
|
27
|
+
export declare function testerSteps(steps: readonly PipelineStep[]): PipelineStep[];
|
|
28
|
+
/**
|
|
29
|
+
* The tester step whose report describes the work as it stands: the last one that reported,
|
|
30
|
+
* else the first tester step in the pipeline (see {@link selectEvidenceStep}).
|
|
31
|
+
*/
|
|
32
|
+
export declare function selectTesterReportStep(steps: readonly PipelineStep[]): PipelineStep | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Index a run's requirement verdicts by the spec's own requirement id, across EVERY tester step
|
|
35
|
+
* in pipeline order.
|
|
36
|
+
*
|
|
37
|
+
* Every tester step, not just the one whose report a `tests` section shows: a pipeline carrying
|
|
38
|
+
* both `tester-api` and `tester-ui` promotes requirements off both kinds' verdicts, so a join
|
|
39
|
+
* reading only the last of them shows "not checked" against requirements the spec already
|
|
40
|
+
* records as `established`.
|
|
41
|
+
*
|
|
42
|
+
* A duplicate id keeps the FIRST verdict, whether it repeats within one report or across two
|
|
43
|
+
* testers, because last-wins would let a trailing `not_covered` quietly erase a real
|
|
44
|
+
* observation, which is the one thing a coverage join exists to prevent.
|
|
45
|
+
*/
|
|
46
|
+
export declare function indexRequirementVerdicts(steps: readonly PipelineStep[]): Map<string, RequirementVerdict>;
|
|
47
|
+
/**
|
|
48
|
+
* One spec requirement paired with what the tester observed about it: the REQUIREMENT →
|
|
49
|
+
* EVIDENCE row both reductions are built from.
|
|
50
|
+
*
|
|
51
|
+
* Deliberately un-scrubbed and un-clamped. A consumer writing onto a rendered surface (a pull
|
|
52
|
+
* request body) owes the text its own boundary treatment, and doing it here would hand the SPA
|
|
53
|
+
* escaped entities it has no reason to render.
|
|
54
|
+
*/
|
|
55
|
+
export interface JoinedRequirement {
|
|
56
|
+
/** The spec requirement's stable id: the join key, and what a reader greps `spec/` for. */
|
|
57
|
+
id: string;
|
|
58
|
+
title: string;
|
|
59
|
+
/** Where it lives in the spec taxonomy. */
|
|
60
|
+
module: string;
|
|
61
|
+
group: string;
|
|
62
|
+
priority: RequirementPriority;
|
|
63
|
+
/**
|
|
64
|
+
* Implementation state as `spec/` recorded it. It travels WITH the verdict because it is what
|
|
65
|
+
* makes `not_met` readable: against an `aspirational` requirement that is in-flight work,
|
|
66
|
+
* against an `established` one it is behaviour the service has lost.
|
|
67
|
+
*/
|
|
68
|
+
state: RequirementState;
|
|
69
|
+
/** What the tester observed; `not_covered` when no tester ruled on it. */
|
|
70
|
+
verdict: RequirementVerdictStatus;
|
|
71
|
+
/** The tester's evidence for the verdict, when it gave any. */
|
|
72
|
+
detail: string | null;
|
|
73
|
+
/** How many acceptance criteria the requirement carries in `spec/`. */
|
|
74
|
+
criteriaCount: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Join the service's in-repo `spec/` to a run's requirement verdicts, in spec order (module →
|
|
78
|
+
* group → requirement).
|
|
79
|
+
*
|
|
80
|
+
* A requirement the tester said nothing about is `not_covered`, NEVER `not_met`: silence means
|
|
81
|
+
* nobody looked, and rendering that as a failure would make every unrelated change look like it
|
|
82
|
+
* broke the service.
|
|
83
|
+
*/
|
|
84
|
+
export declare function joinSpecRequirements(spec: SpecDoc, verdicts: ReadonlyMap<string, RequirementVerdict>): JoinedRequirement[];
|
|
85
|
+
/**
|
|
86
|
+
* The verdict ids the join could NOT place: ids the tester ruled on that the spec does not
|
|
87
|
+
* carry.
|
|
88
|
+
*
|
|
89
|
+
* Shared for the same reason the join is: the difference between a coverage section's rulings
|
|
90
|
+
* and the tester's own is otherwise unexplainable, and it reads as a miscount in whichever of
|
|
91
|
+
* the two the reader trusts less. Two spellings of "which ids went missing" would be a third
|
|
92
|
+
* way for the two documents to print different numbers for one run.
|
|
93
|
+
*
|
|
94
|
+
* It is also the fact that tells an EMPTY join apart from an ABSENT one: a spec declaring no
|
|
95
|
+
* requirements against a tester that ruled on nothing is genuinely nothing to report, while the
|
|
96
|
+
* same spec against a tester that returned verdicts is a spec that moved on under the run, and
|
|
97
|
+
* the verdicts are the only evidence there is.
|
|
98
|
+
*/
|
|
99
|
+
export declare function unmatchedVerdictIds(rows: readonly JoinedRequirement[], verdicts: ReadonlyMap<string, RequirementVerdict>): string[];
|
|
100
|
+
/**
|
|
101
|
+
* The branch a run's `spec/` must be read from: the branch the run pushed its work to, else the
|
|
102
|
+
* repo's default.
|
|
103
|
+
*
|
|
104
|
+
* Stated here because THREE readers need the same answer and two of them had already disagreed:
|
|
105
|
+
* the engine's evidence loader read the run's branch while the SPA's spec fetch read the default,
|
|
106
|
+
* so an in-flight run's outcome card joined this run's verdicts against a spec that does not yet
|
|
107
|
+
* carry the requirements it just ruled on. Every one of those rows lands as "not checked", and
|
|
108
|
+
* the card's counts contradict `GET /api/v1/runs/:runId/outcome` for the same run.
|
|
109
|
+
*
|
|
110
|
+
* The run's branch, not the default, is the truthful denominator: the spec increment this task
|
|
111
|
+
* wrote has not merged yet, and the verdicts were made against the tree as it stands on that
|
|
112
|
+
* branch. Once the pull request merges the two answers converge, which is why the fallback is
|
|
113
|
+
* the default branch rather than an absence.
|
|
114
|
+
*/
|
|
115
|
+
export declare function runSpecBranch(block: Block, defaultBranch: string): string;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a row is a REGRESSION: behaviour the spec records as `established` (observed to hold
|
|
118
|
+
* on some earlier run, which is the only thing that makes it standing behaviour) that this run's
|
|
119
|
+
* tester observed to FAIL.
|
|
120
|
+
*
|
|
121
|
+
* The one derived fact the implementation-state axis exists to make computable, and the only
|
|
122
|
+
* reading of a coverage section that says the change BROKE something rather than merely not
|
|
123
|
+
* finishing it. Left uncomputed, an aspirational failure and a lost behaviour reach a reader as
|
|
124
|
+
* the same `not met` cell.
|
|
125
|
+
*/
|
|
126
|
+
export declare function isRequirementRegression(row: {
|
|
127
|
+
state: RequirementState;
|
|
128
|
+
verdict: RequirementVerdictStatus;
|
|
129
|
+
}): boolean;
|
|
130
|
+
/** How many requirements landed on each verdict, over the WHOLE join and before any cap. */
|
|
131
|
+
export interface RequirementTally {
|
|
132
|
+
met: number;
|
|
133
|
+
notMet: number;
|
|
134
|
+
notCovered: number;
|
|
135
|
+
/** A SUBSET of `notMet`: see {@link isRequirementRegression}. */
|
|
136
|
+
regressions: number;
|
|
137
|
+
total: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Count a join. Over every row and before any cap, so a surface that shows a bounded table still
|
|
141
|
+
* reports the true totals.
|
|
142
|
+
*/
|
|
143
|
+
export declare function tallyRequirements(rows: readonly JoinedRequirement[]): RequirementTally;
|
|
144
|
+
/** How the areas a tester exercised came out. */
|
|
145
|
+
export interface TestOutcomeTally {
|
|
146
|
+
passed: number;
|
|
147
|
+
failed: number;
|
|
148
|
+
skipped: number;
|
|
149
|
+
}
|
|
150
|
+
/** Tally a tester report's per-area outcomes. */
|
|
151
|
+
export declare function tallyTestOutcomes(report: TestReport): TestOutcomeTally;
|
|
152
|
+
//# sourceMappingURL=run-evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-evidence.d.ts","sourceRoot":"","sources":["../src/run-evidence.ts"],"names":[],"mappings":"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"}
|