@cat-factory/contracts 0.262.0 → 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/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/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
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { UI_TESTER_AGENT_KIND } from './visual-pipeline.js';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// The rules for reading a RUN's evidence, stated once for every consumer that reduces it.
|
|
4
|
+
//
|
|
5
|
+
// A finished run is reduced twice today, for two audiences: the engine's PR verification report
|
|
6
|
+
// (what a reviewer needs to believe the change, written onto the pull request and served at
|
|
7
|
+
// `GET /api/v1/runs/:runId/report`) and the run OUTCOME summary (the non-code answer to "what
|
|
8
|
+
// did this run change", served at `GET /api/v1/runs/:runId/outcome` and rendered in the SPA).
|
|
9
|
+
// Two reductions is fine; two sets of RULES is not, and the second one had already drifted from
|
|
10
|
+
// the first in three places before this module existed:
|
|
11
|
+
//
|
|
12
|
+
// - which tester step's verdicts count (the report unions every tester step, the summary read
|
|
13
|
+
// only the last one that reported, so a pipeline carrying `tester-api` beside `tester-ui`
|
|
14
|
+
// got different coverage on the two surfaces);
|
|
15
|
+
// - what `not_covered` counts (the report enumerates the SPEC, so a requirement nobody looked
|
|
16
|
+
// at is reported as unchecked; the summary enumerated the tester's own verdicts, so the same
|
|
17
|
+
// requirement was invisible and both surfaces printed a number called "not covered");
|
|
18
|
+
// - what a REGRESSION is (the same rule, written out twice);
|
|
19
|
+
// - which BRANCH the spec is read from, the one that decides whether the join has anything to
|
|
20
|
+
// match at all (see {@link runSpecBranch}).
|
|
21
|
+
//
|
|
22
|
+
// So the rules live here, in the package both the backend and the SPA compile against, and the
|
|
23
|
+
// two reductions call them rather than restating them. What each surface still owns is its own
|
|
24
|
+
// PRESENTATION and its own absence policy: the report withholds a section it cannot compute and
|
|
25
|
+
// says so in prose, the summary carries a machine-readable gap code the SPA maps to translated
|
|
26
|
+
// copy. Those genuinely differ. The facts underneath may not.
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/** The API tester gate's agent kind. */
|
|
29
|
+
export const TESTER_AGENT_KIND = 'tester-api';
|
|
30
|
+
/**
|
|
31
|
+
* Whether an agent kind is one of the tester gate kinds (API or UI).
|
|
32
|
+
*
|
|
33
|
+
* Here rather than in each consumer because every reduction of a run's test evidence starts by
|
|
34
|
+
* answering it, and the two copies that preceded this one spelled the kinds out as literals on
|
|
35
|
+
* one side and as constants on the other.
|
|
36
|
+
*/
|
|
37
|
+
export function isTesterKind(kind) {
|
|
38
|
+
return kind === TESTER_AGENT_KIND || kind === UI_TESTER_AGENT_KIND;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The step a section should report on: the LAST matching step that carries evidence, else the
|
|
42
|
+
* first matching step.
|
|
43
|
+
*
|
|
44
|
+
* Last-with-evidence, not first-match: a pipeline may legitimately carry the same kind twice (a
|
|
45
|
+
* `ci` gate after the coder and another after the tester), and the later run describes the head
|
|
46
|
+
* as it stands now. Falling back to the first match rather than to nothing is what lets a
|
|
47
|
+
* consumer tell "this pipeline has no such step" from "it has one and it has not reported yet",
|
|
48
|
+
* which are opposite facts that a single `null` states identically.
|
|
49
|
+
*/
|
|
50
|
+
export function selectEvidenceStep(steps, matches, hasEvidence) {
|
|
51
|
+
const matching = steps.filter(matches);
|
|
52
|
+
for (let i = matching.length - 1; i >= 0; i -= 1) {
|
|
53
|
+
if (hasEvidence(matching[i]))
|
|
54
|
+
return matching[i];
|
|
55
|
+
}
|
|
56
|
+
return matching[0];
|
|
57
|
+
}
|
|
58
|
+
/** Every tester step of a run, in pipeline order. */
|
|
59
|
+
export function testerSteps(steps) {
|
|
60
|
+
return steps.filter((step) => isTesterKind(step.agentKind));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The tester step whose report describes the work as it stands: the last one that reported,
|
|
64
|
+
* else the first tester step in the pipeline (see {@link selectEvidenceStep}).
|
|
65
|
+
*/
|
|
66
|
+
export function selectTesterReportStep(steps) {
|
|
67
|
+
return selectEvidenceStep(steps, (step) => isTesterKind(step.agentKind), (step) => step.test?.lastReport != null);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Index a run's requirement verdicts by the spec's own requirement id, across EVERY tester step
|
|
71
|
+
* in pipeline order.
|
|
72
|
+
*
|
|
73
|
+
* Every tester step, not just the one whose report a `tests` section shows: a pipeline carrying
|
|
74
|
+
* both `tester-api` and `tester-ui` promotes requirements off both kinds' verdicts, so a join
|
|
75
|
+
* reading only the last of them shows "not checked" against requirements the spec already
|
|
76
|
+
* records as `established`.
|
|
77
|
+
*
|
|
78
|
+
* A duplicate id keeps the FIRST verdict, whether it repeats within one report or across two
|
|
79
|
+
* testers, because last-wins would let a trailing `not_covered` quietly erase a real
|
|
80
|
+
* observation, which is the one thing a coverage join exists to prevent.
|
|
81
|
+
*/
|
|
82
|
+
export function indexRequirementVerdicts(steps) {
|
|
83
|
+
const byId = new Map();
|
|
84
|
+
for (const step of testerSteps(steps)) {
|
|
85
|
+
for (const verdict of step.test?.lastReport?.requirementVerdicts ?? []) {
|
|
86
|
+
if (!byId.has(verdict.requirementId))
|
|
87
|
+
byId.set(verdict.requirementId, verdict);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return byId;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Join the service's in-repo `spec/` to a run's requirement verdicts, in spec order (module →
|
|
94
|
+
* group → requirement).
|
|
95
|
+
*
|
|
96
|
+
* A requirement the tester said nothing about is `not_covered`, NEVER `not_met`: silence means
|
|
97
|
+
* nobody looked, and rendering that as a failure would make every unrelated change look like it
|
|
98
|
+
* broke the service.
|
|
99
|
+
*/
|
|
100
|
+
export function joinSpecRequirements(spec, verdicts) {
|
|
101
|
+
const rows = [];
|
|
102
|
+
for (const module of spec.modules ?? []) {
|
|
103
|
+
for (const group of module.groups ?? []) {
|
|
104
|
+
for (const requirement of group.requirements ?? []) {
|
|
105
|
+
const verdict = verdicts.get(requirement.id);
|
|
106
|
+
rows.push({
|
|
107
|
+
id: requirement.id,
|
|
108
|
+
title: requirement.title,
|
|
109
|
+
module: module.name,
|
|
110
|
+
group: group.name,
|
|
111
|
+
priority: requirement.priority,
|
|
112
|
+
state: requirement.state ?? 'aspirational',
|
|
113
|
+
verdict: verdict?.status ?? 'not_covered',
|
|
114
|
+
detail: verdict?.detail?.trim() || null,
|
|
115
|
+
criteriaCount: (requirement.acceptance ?? []).length,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return rows;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The verdict ids the join could NOT place: ids the tester ruled on that the spec does not
|
|
124
|
+
* carry.
|
|
125
|
+
*
|
|
126
|
+
* Shared for the same reason the join is: the difference between a coverage section's rulings
|
|
127
|
+
* and the tester's own is otherwise unexplainable, and it reads as a miscount in whichever of
|
|
128
|
+
* the two the reader trusts less. Two spellings of "which ids went missing" would be a third
|
|
129
|
+
* way for the two documents to print different numbers for one run.
|
|
130
|
+
*
|
|
131
|
+
* It is also the fact that tells an EMPTY join apart from an ABSENT one: a spec declaring no
|
|
132
|
+
* requirements against a tester that ruled on nothing is genuinely nothing to report, while the
|
|
133
|
+
* same spec against a tester that returned verdicts is a spec that moved on under the run, and
|
|
134
|
+
* the verdicts are the only evidence there is.
|
|
135
|
+
*/
|
|
136
|
+
export function unmatchedVerdictIds(rows, verdicts) {
|
|
137
|
+
const known = new Set(rows.map((row) => row.id));
|
|
138
|
+
return [...verdicts.keys()].filter((id) => !known.has(id));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The branch a run's `spec/` must be read from: the branch the run pushed its work to, else the
|
|
142
|
+
* repo's default.
|
|
143
|
+
*
|
|
144
|
+
* Stated here because THREE readers need the same answer and two of them had already disagreed:
|
|
145
|
+
* the engine's evidence loader read the run's branch while the SPA's spec fetch read the default,
|
|
146
|
+
* so an in-flight run's outcome card joined this run's verdicts against a spec that does not yet
|
|
147
|
+
* carry the requirements it just ruled on. Every one of those rows lands as "not checked", and
|
|
148
|
+
* the card's counts contradict `GET /api/v1/runs/:runId/outcome` for the same run.
|
|
149
|
+
*
|
|
150
|
+
* The run's branch, not the default, is the truthful denominator: the spec increment this task
|
|
151
|
+
* wrote has not merged yet, and the verdicts were made against the tree as it stands on that
|
|
152
|
+
* branch. Once the pull request merges the two answers converge, which is why the fallback is
|
|
153
|
+
* the default branch rather than an absence.
|
|
154
|
+
*/
|
|
155
|
+
export function runSpecBranch(block, defaultBranch) {
|
|
156
|
+
return block.pullRequest?.branch ?? defaultBranch;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Whether a row is a REGRESSION: behaviour the spec records as `established` (observed to hold
|
|
160
|
+
* on some earlier run, which is the only thing that makes it standing behaviour) that this run's
|
|
161
|
+
* tester observed to FAIL.
|
|
162
|
+
*
|
|
163
|
+
* The one derived fact the implementation-state axis exists to make computable, and the only
|
|
164
|
+
* reading of a coverage section that says the change BROKE something rather than merely not
|
|
165
|
+
* finishing it. Left uncomputed, an aspirational failure and a lost behaviour reach a reader as
|
|
166
|
+
* the same `not met` cell.
|
|
167
|
+
*/
|
|
168
|
+
export function isRequirementRegression(row) {
|
|
169
|
+
return row.state === 'established' && row.verdict === 'not_met';
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Count a join. Over every row and before any cap, so a surface that shows a bounded table still
|
|
173
|
+
* reports the true totals.
|
|
174
|
+
*/
|
|
175
|
+
export function tallyRequirements(rows) {
|
|
176
|
+
const count = (status) => rows.filter((row) => row.verdict === status).length;
|
|
177
|
+
return {
|
|
178
|
+
met: count('met'),
|
|
179
|
+
notMet: count('not_met'),
|
|
180
|
+
notCovered: count('not_covered'),
|
|
181
|
+
regressions: rows.filter(isRequirementRegression).length,
|
|
182
|
+
total: rows.length,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** Tally a tester report's per-area outcomes. */
|
|
186
|
+
export function tallyTestOutcomes(report) {
|
|
187
|
+
const tally = { passed: 0, failed: 0, skipped: 0 };
|
|
188
|
+
for (const outcome of report.outcomes)
|
|
189
|
+
tally[outcome.status] += 1;
|
|
190
|
+
return tally;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=run-evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-evidence.js","sourceRoot":"","sources":["../src/run-evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
import type { Block } from './entities.js';
|
|
3
|
+
import type { ExecutionInstance } from './execution.js';
|
|
4
|
+
import type { ServiceSpecView } from './spec.js';
|
|
5
|
+
/**
|
|
6
|
+
* The wire version of the outcome payload. Bumped when the shape gains something an external
|
|
7
|
+
* consumer would want to notice; never a compatibility switch (the surface is additive, so a
|
|
8
|
+
* consumer written against an older number keeps reading the fields it knows).
|
|
9
|
+
*/
|
|
10
|
+
export declare const RUN_OUTCOME_VERSION = 1;
|
|
11
|
+
/**
|
|
12
|
+
* Where the run stands, in the terms the person reading the outcome cares about. Derived from
|
|
13
|
+
* the BLOCK's status first (it is what the merge lifecycle writes) and from the run only for
|
|
14
|
+
* the states a block cannot distinguish.
|
|
15
|
+
*/
|
|
16
|
+
export declare const outcomeDispositionSchema: v.PicklistSchema<["merged", "awaiting_merge", "in_flight", "needs_attention", "not_run", "unknown"], undefined>;
|
|
17
|
+
export type OutcomeDisposition = v.InferOutput<typeof outcomeDispositionSchema>;
|
|
18
|
+
/** One pull request the run opened: the own-service PR, plus a peer PR per connected repo. */
|
|
19
|
+
export declare const outcomePullRequestSchema: v.ObjectSchema<{
|
|
20
|
+
readonly url: v.StringSchema<undefined>;
|
|
21
|
+
readonly number: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
|
|
22
|
+
readonly branch: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
23
|
+
/** `owner/name` for a PEER repo's PR; null for the task's own service. */
|
|
24
|
+
readonly repo: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
25
|
+
}, undefined>;
|
|
26
|
+
export type OutcomePullRequest = v.InferOutput<typeof outcomePullRequestSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* The gap EVERY evidence section shares: the block names a run (`block.executionId`) the
|
|
29
|
+
* caller could not resolve, so nothing any step recorded is knowable here.
|
|
30
|
+
*
|
|
31
|
+
* It is kept apart from every other gap in this module, which report what a RESOLVED run did
|
|
32
|
+
* or did not produce. "The store does not have this run" and "this pipeline has no tester
|
|
33
|
+
* step" are opposite facts about opposite things, and a summary that reported the second for
|
|
34
|
+
* the first would blame the pipeline for a read that never happened, on the one surface whose
|
|
35
|
+
* whole job is to say what is known and what is not.
|
|
36
|
+
*/
|
|
37
|
+
export declare const runUnavailableGap = "run_unavailable";
|
|
38
|
+
export type RunUnavailableGap = typeof runUnavailableGap;
|
|
39
|
+
/** Why there is no requirement coverage to show. Each needs a different reaction. */
|
|
40
|
+
export declare const requirementsGapSchema: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported", "no_verdicts", "no_requirements"], undefined>;
|
|
41
|
+
export type RequirementsGap = v.InferOutput<typeof requirementsGapSchema>;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the coverage was counted against the service's `spec/`, or only against the ids the
|
|
44
|
+
* tester keyed its verdicts by.
|
|
45
|
+
*
|
|
46
|
+
* `joined` is the real answer: every requirement the service declares is a row, so one nobody
|
|
47
|
+
* looked at is reported as unchecked. `not_read` is the degraded one, and it is a different
|
|
48
|
+
* DENOMINATOR rather than a cosmetic loss of titles: the counts describe what the tester ruled
|
|
49
|
+
* on and say nothing about what it skipped. It is a real state on both consumers (the SPA
|
|
50
|
+
* renders before its spec fetch lands; a deployment with no VCS wired can never read one), so
|
|
51
|
+
* it is stated rather than collapsed into an absence.
|
|
52
|
+
*/
|
|
53
|
+
export declare const outcomeSpecJoinSchema: v.PicklistSchema<["joined", "not_read"], undefined>;
|
|
54
|
+
export type OutcomeSpecJoin = v.InferOutput<typeof outcomeSpecJoinSchema>;
|
|
55
|
+
/** One requirement, paired with what the tester observed about it. */
|
|
56
|
+
export declare const outcomeRequirementSchema: v.ObjectSchema<{
|
|
57
|
+
/** The spec requirement id: the join key, and all there is when the spec was not read. */
|
|
58
|
+
readonly id: v.StringSchema<undefined>;
|
|
59
|
+
/** The requirement's headline from `spec/`; null on an unjoined row. */
|
|
60
|
+
readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
61
|
+
readonly verdict: v.PicklistSchema<["met", "not_met", "not_covered"], undefined>;
|
|
62
|
+
/** What the tester observed, when it said. */
|
|
63
|
+
readonly detail: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
64
|
+
/** Implementation state as `spec/` recorded it, or null when unjoined. */
|
|
65
|
+
readonly state: v.NullableSchema<v.PicklistSchema<["aspirational", "established"], undefined>, undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* An `established` requirement the tester observed to FAIL: behaviour the platform had
|
|
68
|
+
* previously seen hold and no longer does. Computed here, never read off a report, and the
|
|
69
|
+
* one reading of this section that says the change BROKE something rather than merely not
|
|
70
|
+
* finishing it. An `aspirational` requirement failing is in-flight work, not a regression.
|
|
71
|
+
*/
|
|
72
|
+
readonly regression: v.BooleanSchema<undefined>;
|
|
73
|
+
}, undefined>;
|
|
74
|
+
export type OutcomeRequirement = v.InferOutput<typeof outcomeRequirementSchema>;
|
|
75
|
+
export declare const outcomeRequirementsSchema: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
76
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
77
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported", "no_verdicts", "no_requirements"], undefined>;
|
|
78
|
+
}, undefined>, v.ObjectSchema<{
|
|
79
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
80
|
+
/** What the counts below are counted over. See {@link outcomeSpecJoinSchema}. */
|
|
81
|
+
readonly spec: v.PicklistSchema<["joined", "not_read"], undefined>;
|
|
82
|
+
readonly met: v.NumberSchema<undefined>;
|
|
83
|
+
readonly notMet: v.NumberSchema<undefined>;
|
|
84
|
+
readonly notCovered: v.NumberSchema<undefined>;
|
|
85
|
+
/** A SUBSET of `notMet`; see {@link outcomeRequirementSchema.entries.regression}. */
|
|
86
|
+
readonly regressions: v.NumberSchema<undefined>;
|
|
87
|
+
/**
|
|
88
|
+
* `met + notMet + notCovered`, and the DENOMINATOR the three are read against. Carried rather
|
|
89
|
+
* than left to the reader to add up, because what it counts depends on `spec`: joined, it is
|
|
90
|
+
* every requirement the service declares; unjoined, only the ones the tester ruled on.
|
|
91
|
+
*/
|
|
92
|
+
readonly total: v.NumberSchema<undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Verdicts the tester returned against ids the spec does not carry, which the join can
|
|
95
|
+
* neither place nor count. Non-zero means the spec moved on under the tester (or that it
|
|
96
|
+
* keyed its verdicts by something else), and a reader comparing the totals to the tester's
|
|
97
|
+
* own report needs to know the difference is not a miscount. Always 0 on a `not_read`
|
|
98
|
+
* section, where there is nothing to match against.
|
|
99
|
+
*/
|
|
100
|
+
readonly unmatchedVerdicts: v.NumberSchema<undefined>;
|
|
101
|
+
/** Regressions first, then failures, then what was met, then what nobody checked. */
|
|
102
|
+
readonly entries: v.ArraySchema<v.ObjectSchema<{
|
|
103
|
+
/** The spec requirement id: the join key, and all there is when the spec was not read. */
|
|
104
|
+
readonly id: v.StringSchema<undefined>;
|
|
105
|
+
/** The requirement's headline from `spec/`; null on an unjoined row. */
|
|
106
|
+
readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
107
|
+
readonly verdict: v.PicklistSchema<["met", "not_met", "not_covered"], undefined>;
|
|
108
|
+
/** What the tester observed, when it said. */
|
|
109
|
+
readonly detail: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
110
|
+
/** Implementation state as `spec/` recorded it, or null when unjoined. */
|
|
111
|
+
readonly state: v.NullableSchema<v.PicklistSchema<["aspirational", "established"], undefined>, undefined>;
|
|
112
|
+
/**
|
|
113
|
+
* An `established` requirement the tester observed to FAIL: behaviour the platform had
|
|
114
|
+
* previously seen hold and no longer does. Computed here, never read off a report, and the
|
|
115
|
+
* one reading of this section that says the change BROKE something rather than merely not
|
|
116
|
+
* finishing it. An `aspirational` requirement failing is in-flight work, not a regression.
|
|
117
|
+
*/
|
|
118
|
+
readonly regression: v.BooleanSchema<undefined>;
|
|
119
|
+
}, undefined>, undefined>;
|
|
120
|
+
}, undefined>], undefined>;
|
|
121
|
+
export type OutcomeRequirements = v.InferOutput<typeof outcomeRequirementsSchema>;
|
|
122
|
+
export declare const testsGapSchema: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported"], undefined>;
|
|
123
|
+
export type TestsGap = v.InferOutput<typeof testsGapSchema>;
|
|
124
|
+
/**
|
|
125
|
+
* The tester's disposition. `could_not_run` is kept apart from `concerns` because they call
|
|
126
|
+
* for opposite reactions: one is a change with bugs in it, the other is a change nobody
|
|
127
|
+
* managed to exercise at all, and a report that collapses them reads as tested either way.
|
|
128
|
+
*/
|
|
129
|
+
export declare const testsVerdictSchema: v.PicklistSchema<["greenlit", "concerns", "could_not_run"], undefined>;
|
|
130
|
+
export type TestsVerdict = v.InferOutput<typeof testsVerdictSchema>;
|
|
131
|
+
export declare const outcomeConcernSchema: v.ObjectSchema<{
|
|
132
|
+
readonly title: v.StringSchema<undefined>;
|
|
133
|
+
readonly severity: v.PicklistSchema<["low", "medium", "high", "critical"], undefined>;
|
|
134
|
+
}, undefined>;
|
|
135
|
+
export type OutcomeConcern = v.InferOutput<typeof outcomeConcernSchema>;
|
|
136
|
+
export declare const outcomeTestsSchema: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
137
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
138
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported"], undefined>;
|
|
139
|
+
}, undefined>, v.ObjectSchema<{
|
|
140
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
141
|
+
readonly verdict: v.PicklistSchema<["greenlit", "concerns", "could_not_run"], undefined>;
|
|
142
|
+
/** The tester's own prose about the session, attributed as such at the render site. */
|
|
143
|
+
readonly summary: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
144
|
+
/** Verbatim reason the tester could not run at all; null unless `could_not_run`. */
|
|
145
|
+
readonly abortReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
146
|
+
/** What it exercised, by name. */
|
|
147
|
+
readonly areas: v.ArraySchema<v.StringSchema<undefined>, undefined>;
|
|
148
|
+
readonly passed: v.NumberSchema<undefined>;
|
|
149
|
+
readonly failed: v.NumberSchema<undefined>;
|
|
150
|
+
readonly skipped: v.NumberSchema<undefined>;
|
|
151
|
+
readonly concerns: v.ArraySchema<v.ObjectSchema<{
|
|
152
|
+
readonly title: v.StringSchema<undefined>;
|
|
153
|
+
readonly severity: v.PicklistSchema<["low", "medium", "high", "critical"], undefined>;
|
|
154
|
+
}, undefined>, undefined>;
|
|
155
|
+
readonly environment: v.NullableSchema<v.PicklistSchema<["local", "ephemeral"], undefined>, undefined>;
|
|
156
|
+
}, undefined>], undefined>;
|
|
157
|
+
export type OutcomeTests = v.InferOutput<typeof outcomeTestsSchema>;
|
|
158
|
+
export declare const visualsGapSchema: v.PicklistSchema<["run_unavailable", "no_visual_step", "none_captured"], undefined>;
|
|
159
|
+
export type VisualsGap = v.InferOutput<typeof visualsGapSchema>;
|
|
160
|
+
/** One captured view, paired with the reference design it was reviewed against when there is one. */
|
|
161
|
+
export declare const outcomeVisualSchema: v.ObjectSchema<{
|
|
162
|
+
readonly view: v.StringSchema<undefined>;
|
|
163
|
+
readonly artifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
164
|
+
readonly referenceArtifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
165
|
+
}, undefined>;
|
|
166
|
+
export type OutcomeVisual = v.InferOutput<typeof outcomeVisualSchema>;
|
|
167
|
+
export declare const outcomeVisualsSchema: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
168
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
169
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_visual_step", "none_captured"], undefined>;
|
|
170
|
+
/** The gate's own verbatim explanation, when it recorded one. Detail, never the headline. */
|
|
171
|
+
readonly detail: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
172
|
+
}, undefined>, v.ObjectSchema<{
|
|
173
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
174
|
+
/**
|
|
175
|
+
* Which producer the views came from. `visual_confirm` pairs were put in front of a
|
|
176
|
+
* human and carry a verdict; `tester` shots are captures nobody was asked about, and the
|
|
177
|
+
* summary must not let the second read as the first.
|
|
178
|
+
*/
|
|
179
|
+
readonly source: v.PicklistSchema<["visual_confirm", "tester"], undefined>;
|
|
180
|
+
/** The gate's phase when the views came from it: awaiting a human, fixing, or approved. */
|
|
181
|
+
readonly phase: v.NullableSchema<v.PicklistSchema<["awaiting_human", "fixing", "approved"], undefined>, undefined>;
|
|
182
|
+
readonly views: v.ArraySchema<v.ObjectSchema<{
|
|
183
|
+
readonly view: v.StringSchema<undefined>;
|
|
184
|
+
readonly artifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
185
|
+
readonly referenceArtifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
186
|
+
}, undefined>, undefined>;
|
|
187
|
+
}, undefined>], undefined>;
|
|
188
|
+
export type OutcomeVisuals = v.InferOutput<typeof outcomeVisualsSchema>;
|
|
189
|
+
/** The three recorded machine verdicts a non-code reader still needs: did it build, does it work. */
|
|
190
|
+
export declare const outcomeCheckKindSchema: v.PicklistSchema<["ci", "validation", "reproduction"], undefined>;
|
|
191
|
+
export type OutcomeCheckKind = v.InferOutput<typeof outcomeCheckKindSchema>;
|
|
192
|
+
export declare const outcomeCheckStateSchema: v.PicklistSchema<["pass", "fail", "pending", "inconclusive"], undefined>;
|
|
193
|
+
export type OutcomeCheckState = v.InferOutput<typeof outcomeCheckStateSchema>;
|
|
194
|
+
export declare const outcomeCheckSchema: v.ObjectSchema<{
|
|
195
|
+
readonly kind: v.PicklistSchema<["ci", "validation", "reproduction"], undefined>;
|
|
196
|
+
readonly state: v.PicklistSchema<["pass", "fail", "pending", "inconclusive"], undefined>;
|
|
197
|
+
/**
|
|
198
|
+
* The producer's own qualifier, when the state alone would under-report it: the reproduction
|
|
199
|
+
* verdict that earned an `inconclusive`. Rendered through an exhaustive map, never as prose.
|
|
200
|
+
*/
|
|
201
|
+
readonly reproduction: v.NullableSchema<v.PicklistSchema<["reproduced", "inconclusive", "declared_infeasible"], undefined>, undefined>;
|
|
202
|
+
}, undefined>;
|
|
203
|
+
export type OutcomeCheck = v.InferOutput<typeof outcomeCheckSchema>;
|
|
204
|
+
export declare const runOutcomeSchema: v.ObjectSchema<{
|
|
205
|
+
/** See {@link RUN_OUTCOME_VERSION}. */
|
|
206
|
+
readonly version: v.NumberSchema<undefined>;
|
|
207
|
+
readonly disposition: v.PicklistSchema<["merged", "awaiting_merge", "in_flight", "needs_attention", "not_run", "unknown"], undefined>;
|
|
208
|
+
/** The task's title: the product-language name of what was asked for. */
|
|
209
|
+
readonly title: v.StringSchema<undefined>;
|
|
210
|
+
/** The requester's own description of the ask, trimmed; null when the task carried none. */
|
|
211
|
+
readonly ask: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
212
|
+
/** Every PR the run opened, so the diff stays exactly one click from the summary. */
|
|
213
|
+
readonly pullRequests: v.ArraySchema<v.ObjectSchema<{
|
|
214
|
+
readonly url: v.StringSchema<undefined>;
|
|
215
|
+
readonly number: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
|
|
216
|
+
readonly branch: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
217
|
+
/** `owner/name` for a PEER repo's PR; null for the task's own service. */
|
|
218
|
+
readonly repo: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
219
|
+
}, undefined>, undefined>;
|
|
220
|
+
readonly requirements: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
221
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
222
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported", "no_verdicts", "no_requirements"], undefined>;
|
|
223
|
+
}, undefined>, v.ObjectSchema<{
|
|
224
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
225
|
+
/** What the counts below are counted over. See {@link outcomeSpecJoinSchema}. */
|
|
226
|
+
readonly spec: v.PicklistSchema<["joined", "not_read"], undefined>;
|
|
227
|
+
readonly met: v.NumberSchema<undefined>;
|
|
228
|
+
readonly notMet: v.NumberSchema<undefined>;
|
|
229
|
+
readonly notCovered: v.NumberSchema<undefined>;
|
|
230
|
+
/** A SUBSET of `notMet`; see {@link outcomeRequirementSchema.entries.regression}. */
|
|
231
|
+
readonly regressions: v.NumberSchema<undefined>;
|
|
232
|
+
/**
|
|
233
|
+
* `met + notMet + notCovered`, and the DENOMINATOR the three are read against. Carried rather
|
|
234
|
+
* than left to the reader to add up, because what it counts depends on `spec`: joined, it is
|
|
235
|
+
* every requirement the service declares; unjoined, only the ones the tester ruled on.
|
|
236
|
+
*/
|
|
237
|
+
readonly total: v.NumberSchema<undefined>;
|
|
238
|
+
/**
|
|
239
|
+
* Verdicts the tester returned against ids the spec does not carry, which the join can
|
|
240
|
+
* neither place nor count. Non-zero means the spec moved on under the tester (or that it
|
|
241
|
+
* keyed its verdicts by something else), and a reader comparing the totals to the tester's
|
|
242
|
+
* own report needs to know the difference is not a miscount. Always 0 on a `not_read`
|
|
243
|
+
* section, where there is nothing to match against.
|
|
244
|
+
*/
|
|
245
|
+
readonly unmatchedVerdicts: v.NumberSchema<undefined>;
|
|
246
|
+
/** Regressions first, then failures, then what was met, then what nobody checked. */
|
|
247
|
+
readonly entries: v.ArraySchema<v.ObjectSchema<{
|
|
248
|
+
/** The spec requirement id: the join key, and all there is when the spec was not read. */
|
|
249
|
+
readonly id: v.StringSchema<undefined>;
|
|
250
|
+
/** The requirement's headline from `spec/`; null on an unjoined row. */
|
|
251
|
+
readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
252
|
+
readonly verdict: v.PicklistSchema<["met", "not_met", "not_covered"], undefined>;
|
|
253
|
+
/** What the tester observed, when it said. */
|
|
254
|
+
readonly detail: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
255
|
+
/** Implementation state as `spec/` recorded it, or null when unjoined. */
|
|
256
|
+
readonly state: v.NullableSchema<v.PicklistSchema<["aspirational", "established"], undefined>, undefined>;
|
|
257
|
+
/**
|
|
258
|
+
* An `established` requirement the tester observed to FAIL: behaviour the platform had
|
|
259
|
+
* previously seen hold and no longer does. Computed here, never read off a report, and the
|
|
260
|
+
* one reading of this section that says the change BROKE something rather than merely not
|
|
261
|
+
* finishing it. An `aspirational` requirement failing is in-flight work, not a regression.
|
|
262
|
+
*/
|
|
263
|
+
readonly regression: v.BooleanSchema<undefined>;
|
|
264
|
+
}, undefined>, undefined>;
|
|
265
|
+
}, undefined>], undefined>;
|
|
266
|
+
readonly tests: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
267
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
268
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_tester_step", "tester_not_reported"], undefined>;
|
|
269
|
+
}, undefined>, v.ObjectSchema<{
|
|
270
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
271
|
+
readonly verdict: v.PicklistSchema<["greenlit", "concerns", "could_not_run"], undefined>;
|
|
272
|
+
/** The tester's own prose about the session, attributed as such at the render site. */
|
|
273
|
+
readonly summary: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
274
|
+
/** Verbatim reason the tester could not run at all; null unless `could_not_run`. */
|
|
275
|
+
readonly abortReason: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
276
|
+
/** What it exercised, by name. */
|
|
277
|
+
readonly areas: v.ArraySchema<v.StringSchema<undefined>, undefined>;
|
|
278
|
+
readonly passed: v.NumberSchema<undefined>;
|
|
279
|
+
readonly failed: v.NumberSchema<undefined>;
|
|
280
|
+
readonly skipped: v.NumberSchema<undefined>;
|
|
281
|
+
readonly concerns: v.ArraySchema<v.ObjectSchema<{
|
|
282
|
+
readonly title: v.StringSchema<undefined>;
|
|
283
|
+
readonly severity: v.PicklistSchema<["low", "medium", "high", "critical"], undefined>;
|
|
284
|
+
}, undefined>, undefined>;
|
|
285
|
+
readonly environment: v.NullableSchema<v.PicklistSchema<["local", "ephemeral"], undefined>, undefined>;
|
|
286
|
+
}, undefined>], undefined>;
|
|
287
|
+
readonly visuals: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
288
|
+
readonly status: v.LiteralSchema<"absent", undefined>;
|
|
289
|
+
readonly gap: v.PicklistSchema<["run_unavailable", "no_visual_step", "none_captured"], undefined>;
|
|
290
|
+
/** The gate's own verbatim explanation, when it recorded one. Detail, never the headline. */
|
|
291
|
+
readonly detail: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
292
|
+
}, undefined>, v.ObjectSchema<{
|
|
293
|
+
readonly status: v.LiteralSchema<"reported", undefined>;
|
|
294
|
+
/**
|
|
295
|
+
* Which producer the views came from. `visual_confirm` pairs were put in front of a
|
|
296
|
+
* human and carry a verdict; `tester` shots are captures nobody was asked about, and the
|
|
297
|
+
* summary must not let the second read as the first.
|
|
298
|
+
*/
|
|
299
|
+
readonly source: v.PicklistSchema<["visual_confirm", "tester"], undefined>;
|
|
300
|
+
/** The gate's phase when the views came from it: awaiting a human, fixing, or approved. */
|
|
301
|
+
readonly phase: v.NullableSchema<v.PicklistSchema<["awaiting_human", "fixing", "approved"], undefined>, undefined>;
|
|
302
|
+
readonly views: v.ArraySchema<v.ObjectSchema<{
|
|
303
|
+
readonly view: v.StringSchema<undefined>;
|
|
304
|
+
readonly artifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
305
|
+
readonly referenceArtifactId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
306
|
+
}, undefined>, undefined>;
|
|
307
|
+
}, undefined>], undefined>;
|
|
308
|
+
/** Only the checks that actually ran: an absent check is omitted, never rendered as passing. */
|
|
309
|
+
readonly checks: v.ArraySchema<v.ObjectSchema<{
|
|
310
|
+
readonly kind: v.PicklistSchema<["ci", "validation", "reproduction"], undefined>;
|
|
311
|
+
readonly state: v.PicklistSchema<["pass", "fail", "pending", "inconclusive"], undefined>;
|
|
312
|
+
/**
|
|
313
|
+
* The producer's own qualifier, when the state alone would under-report it: the reproduction
|
|
314
|
+
* verdict that earned an `inconclusive`. Rendered through an exhaustive map, never as prose.
|
|
315
|
+
*/
|
|
316
|
+
readonly reproduction: v.NullableSchema<v.PicklistSchema<["reproduced", "inconclusive", "declared_infeasible"], undefined>, undefined>;
|
|
317
|
+
}, undefined>, undefined>;
|
|
318
|
+
/**
|
|
319
|
+
* What a BOUNDED rendering of this summary had to leave out, one note per capped list
|
|
320
|
+
* (`"requirements.entries: showing 200 of 480"`), in the same vocabulary the verification
|
|
321
|
+
* report's own `truncations` uses. Empty whenever nothing was dropped, which is every
|
|
322
|
+
* ordinary run and every composition the SPA does (it renders from state it already holds and
|
|
323
|
+
* caps nothing).
|
|
324
|
+
*
|
|
325
|
+
* It exists because the counts above are computed over the WHOLE join, before any cap: a
|
|
326
|
+
* consumer that found 200 rows under a `total` of 480 and no note would have to guess whether
|
|
327
|
+
* the tail was never ruled on. A cap that is not a plain prefix says so in its note, since
|
|
328
|
+
* `entries` is ordered by SEVERITY and the rows a cap drops are therefore the least severe
|
|
329
|
+
* ones rather than the end of the spec.
|
|
330
|
+
*/
|
|
331
|
+
readonly truncations: v.ArraySchema<v.StringSchema<undefined>, undefined>;
|
|
332
|
+
}, undefined>;
|
|
333
|
+
export type RunOutcome = v.InferOutput<typeof runOutcomeSchema>;
|
|
334
|
+
/**
|
|
335
|
+
* Parse-or-throw an outcome payload, for any consumer proving the JSON it holds is this shape.
|
|
336
|
+
*/
|
|
337
|
+
export declare function parseRunOutcome(value: unknown): RunOutcome;
|
|
338
|
+
export interface ComposeRunOutcomeInput {
|
|
339
|
+
block: Block;
|
|
340
|
+
/**
|
|
341
|
+
* The run, or null when the caller has none. Null is TWO facts, and the block tells them
|
|
342
|
+
* apart: a task with no `executionId` never ran, while a task that names one the caller
|
|
343
|
+
* could not resolve has run and this summary simply cannot see it (see
|
|
344
|
+
* {@link runUnavailableGap}). Callers pass what their store holds and never substitute one
|
|
345
|
+
* for the other.
|
|
346
|
+
*/
|
|
347
|
+
instance: ExecutionInstance | null;
|
|
348
|
+
/** The enclosing service's spec, when it has been loaded. Absent ⇒ ids without titles. */
|
|
349
|
+
spec?: ServiceSpecView | null;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Compose a run's outcome summary from what the run already carries. Pure: every input is a
|
|
353
|
+
* value the caller read off its store (the SPA) or off its repositories (the API), so the whole
|
|
354
|
+
* reduction unit-tests without mounting the window that renders it, and the two surfaces cannot
|
|
355
|
+
* answer the same question differently.
|
|
356
|
+
*/
|
|
357
|
+
export declare function composeRunOutcome({ block, instance, spec }: ComposeRunOutcomeInput): RunOutcome;
|
|
358
|
+
/**
|
|
359
|
+
* Whether a run has anything an outcome summary could show beyond the task's own title: a PR to
|
|
360
|
+
* open, or a step that recorded evidence. EVERY entry point asks this (the board card and the
|
|
361
|
+
* inspector alike, off the one reduction, so they can never disagree) so the affordance appears
|
|
362
|
+
* on a run that produced something and stays absent on one that has not yet, rather than
|
|
363
|
+
* offering a summary whose every section reads "nothing here".
|
|
364
|
+
*
|
|
365
|
+
* A run this summary could not resolve answers false unless the block still carries a pull
|
|
366
|
+
* request: there is nothing to show, and an affordance that opened onto four "not loaded"
|
|
367
|
+
* notices would be the same empty card by another route.
|
|
368
|
+
*/
|
|
369
|
+
export declare function hasOutcomeToShow(outcome: RunOutcome): boolean;
|
|
370
|
+
//# sourceMappingURL=run-outcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-outcome.d.ts","sourceRoot":"","sources":["../src/run-outcome.ts"],"names":[],"mappings":"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"}
|