@cat-factory/contracts 0.308.1 → 0.310.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/agent-presentation.d.ts +16 -2
- package/dist/agent-presentation.d.ts.map +1 -1
- package/dist/agent-presentation.js +7 -0
- package/dist/agent-presentation.js.map +1 -1
- package/dist/companion-state.d.ts +1 -0
- package/dist/companion-state.d.ts.map +1 -1
- package/dist/companion.d.ts +1 -0
- package/dist/companion.d.ts.map +1 -1
- package/dist/companion.js +18 -7
- package/dist/companion.js.map +1 -1
- package/dist/entities.d.ts +1 -1
- package/dist/execution.d.ts +6 -0
- package/dist/execution.d.ts.map +1 -1
- package/dist/pipeline-purpose-vocabulary.d.ts +8 -3
- package/dist/pipeline-purpose-vocabulary.d.ts.map +1 -1
- package/dist/pipeline-purpose-vocabulary.js +14 -2
- package/dist/pipeline-purpose-vocabulary.js.map +1 -1
- package/dist/pipeline-purpose.d.ts +20 -12
- package/dist/pipeline-purpose.d.ts.map +1 -1
- package/dist/pipeline-purpose.js +79 -23
- package/dist/pipeline-purpose.js.map +1 -1
- package/dist/public-decisions.d.ts +88 -13
- package/dist/public-decisions.d.ts.map +1 -1
- package/dist/public-decisions.js +36 -5
- package/dist/public-decisions.js.map +1 -1
- package/dist/requests.d.ts +2 -2
- package/dist/routes/agent-runs.d.ts +6 -0
- package/dist/routes/agent-runs.d.ts.map +1 -1
- package/dist/routes/bug-hunt.d.ts +6 -0
- package/dist/routes/bug-hunt.d.ts.map +1 -1
- package/dist/routes/execution.d.ts +27 -0
- package/dist/routes/execution.d.ts.map +1 -1
- package/dist/routes/human-review.d.ts +3 -0
- package/dist/routes/human-review.d.ts.map +1 -1
- package/dist/routes/human-test.d.ts +15 -0
- package/dist/routes/human-test.d.ts.map +1 -1
- package/dist/routes/pipelines.d.ts +8 -8
- package/dist/routes/public-decisions.d.ts +164 -0
- package/dist/routes/public-decisions.d.ts.map +1 -1
- package/dist/routes/visual-confirm.d.ts +9 -0
- package/dist/routes/visual-confirm.d.ts.map +1 -1
- package/dist/routes/workspaces.d.ts +10 -4
- package/dist/routes/workspaces.d.ts.map +1 -1
- package/dist/snapshot.d.ts +5 -2
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/step-decisions.d.ts +139 -0
- package/dist/step-decisions.d.ts.map +1 -1
- package/dist/step-decisions.js +117 -0
- package/dist/step-decisions.js.map +1 -1
- package/dist/visual-pipeline.d.ts +24 -1
- package/dist/visual-pipeline.d.ts.map +1 -1
- package/dist/visual-pipeline.js +44 -3
- package/dist/visual-pipeline.js.map +1 -1
- package/package.json +1 -1
package/dist/step-decisions.js
CHANGED
|
@@ -23,6 +23,65 @@ export const decisionSchema = v.object({
|
|
|
23
23
|
options: v.array(v.string()),
|
|
24
24
|
chosen: v.nullable(v.string()),
|
|
25
25
|
});
|
|
26
|
+
/**
|
|
27
|
+
* How urgently a review comment must be acted on, worst first. The three levels are the ones a
|
|
28
|
+
* reviewer already writes as prose group labels ("Must fix" / "Should fix" / "Minor"), promoted to
|
|
29
|
+
* a field so the ENGINE can act on them rather than a human having to read the summary to find out
|
|
30
|
+
* what blocks the work.
|
|
31
|
+
*
|
|
32
|
+
* `blocker` is the load-bearing member and the only one with mechanical force: while a companion's
|
|
33
|
+
* latest verdict carries one, the producer is reworked and the run does not advance past the step,
|
|
34
|
+
* whatever the overall rating says (see {@link hasBlockingReviewComments} and kernel's
|
|
35
|
+
* `disposeCompanionVerdict`). A rating is one number over a whole deliverable, so a review that
|
|
36
|
+
* found something genuinely unshippable could still average above the bar and be waved through;
|
|
37
|
+
* that is the gap this closes. `major` and `minor` differ only in how a reader (and a reworking
|
|
38
|
+
* producer) should prioritise them.
|
|
39
|
+
*/
|
|
40
|
+
export const reviewCommentSeveritySchema = v.picklist(['blocker', 'major', 'minor']);
|
|
41
|
+
/** Rank of a {@link ReviewCommentSeverity}, for worst-first ordering and "at or above" tests. */
|
|
42
|
+
export const REVIEW_COMMENT_SEVERITY_RANK = {
|
|
43
|
+
minor: 0,
|
|
44
|
+
major: 1,
|
|
45
|
+
blocker: 2,
|
|
46
|
+
};
|
|
47
|
+
const REVIEW_COMMENT_SEVERITY_SET = new Set(reviewCommentSeveritySchema.options);
|
|
48
|
+
/**
|
|
49
|
+
* Whether a value is still a member of the vocabulary — DERIVED from the picklist, so it cannot
|
|
50
|
+
* drift from it the way a hand-written second list would.
|
|
51
|
+
*
|
|
52
|
+
* The vocabulary is closed but PERSISTED (a verdict's `comments`, a gate's `comments`, a step's
|
|
53
|
+
* `rework.comments`), and the schema's `severity` fallback does NOT cover those reads: a stored run
|
|
54
|
+
* row is mapped onto {@link StepReviewComment} by the facade repositories, never re-parsed, so the
|
|
55
|
+
* fallback runs on the MODEL REPLY and nowhere else. A member retired from the union therefore goes
|
|
56
|
+
* on existing in saved rows with its type claiming otherwise, and every `Record<ReviewCommentSeverity, …>`
|
|
57
|
+
* over it is total against the TYPE and partial against the DATA. Narrow with this at the read
|
|
58
|
+
* boundary and render the negative case as the unrecognised level it is.
|
|
59
|
+
*
|
|
60
|
+
* A retired member here is NAMED rather than dropped or mapped onto a current one, for the reason
|
|
61
|
+
* `isBinaryModality` names its own: nothing knows which surviving level was meant, and the reader
|
|
62
|
+
* that meets a stale value first is the panel asking a person to act on the finding. What it must
|
|
63
|
+
* never do is claim an urgency nobody graded. It carries no mechanical force either (a stale value
|
|
64
|
+
* is not a `blocker`), so retiring a member means restating the stored rows in the same change;
|
|
65
|
+
* this is what keeps the interim honest instead of invisible.
|
|
66
|
+
*/
|
|
67
|
+
export function isReviewCommentSeverity(value) {
|
|
68
|
+
return REVIEW_COMMENT_SEVERITY_SET.has(value);
|
|
69
|
+
}
|
|
70
|
+
/** Where an ungraded comment (and an unrecognised level) sorts: below every graded one. */
|
|
71
|
+
export const UNGRADED_REVIEW_COMMENT_RANK = -1;
|
|
72
|
+
/**
|
|
73
|
+
* The rank a comment's severity sorts and compares at: {@link REVIEW_COMMENT_SEVERITY_RANK} while
|
|
74
|
+
* the vocabulary holds it, and {@link UNGRADED_REVIEW_COMMENT_RANK} when the comment carries no
|
|
75
|
+
* severity (a person's) or one this build no longer knows ({@link isReviewCommentSeverity}).
|
|
76
|
+
*
|
|
77
|
+
* The ONE place that lookup happens, so an unrecognised value cannot reach the `Record` raw and
|
|
78
|
+
* come back `undefined` — which sorts by `NaN` and compares false against every floor at once.
|
|
79
|
+
*/
|
|
80
|
+
export function reviewCommentSeverityRank(severity) {
|
|
81
|
+
return severity !== undefined && isReviewCommentSeverity(severity)
|
|
82
|
+
? REVIEW_COMMENT_SEVERITY_RANK[severity]
|
|
83
|
+
: UNGRADED_REVIEW_COMMENT_RANK;
|
|
84
|
+
}
|
|
26
85
|
/**
|
|
27
86
|
* One GitHub-review-style comment left on a specific block or item of an agent's
|
|
28
87
|
* proposal — either by a human reviewing an approval gate, or by a quality
|
|
@@ -56,9 +115,63 @@ export const stepReviewCommentSchema = v.object({
|
|
|
56
115
|
* items rather than free prose. Absent for prose-range comments.
|
|
57
116
|
*/
|
|
58
117
|
anchorId: v.optional(v.string()),
|
|
118
|
+
/**
|
|
119
|
+
* How urgently this point must be acted on (see {@link reviewCommentSeveritySchema}).
|
|
120
|
+
*
|
|
121
|
+
* Absent on a HUMAN's comment, which carries no such grading: a person requesting changes on an
|
|
122
|
+
* approval gate is already holding the run, so there is nothing for a severity to decide. Absent
|
|
123
|
+
* too on a comment recorded before this field existed. An absent severity is therefore read as
|
|
124
|
+
* "ungraded", NEVER as a blocker and never as a nit — the one reader that acts on the value
|
|
125
|
+
* ({@link hasBlockingReviewComments}) asks only whether a `blocker` is present.
|
|
126
|
+
*
|
|
127
|
+
* An out-of-vocabulary value from a model reads as `major`, the same "unreadable severity reads
|
|
128
|
+
* as its safe default" rule the judge and PR-review findings use. `major` rather than either
|
|
129
|
+
* extreme on purpose: a typo must not manufacture a hard stop, and it must not silently retire
|
|
130
|
+
* one either, so it lands where the point still costs a rework round without holding the run.
|
|
131
|
+
*
|
|
132
|
+
* That fallback covers the MODEL REPLY, which is the only input this schema parses. A stored row
|
|
133
|
+
* is mapped onto the type by the facade repositories rather than re-parsed, so a value this build
|
|
134
|
+
* has retired reaches a reader with the fallback never having run: narrow those reads with
|
|
135
|
+
* {@link isReviewCommentSeverity} / {@link reviewCommentSeverityRank}.
|
|
136
|
+
*/
|
|
137
|
+
severity: v.optional(v.fallback(reviewCommentSeveritySchema, 'major')),
|
|
59
138
|
/** The reviewer's note on this block / item. */
|
|
60
139
|
body: v.string(),
|
|
61
140
|
});
|
|
141
|
+
/**
|
|
142
|
+
* The comments that MUST be fixed before the work moves on, worst-first-ordered input aside.
|
|
143
|
+
*
|
|
144
|
+
* The pure rule, in contracts rather than in the engine, because both sides have to agree about
|
|
145
|
+
* it: the engine decides whether the run advances, and the SPA states on the parked step WHY it
|
|
146
|
+
* stopped and which points to look at. Restated on each side, the panel would eventually count
|
|
147
|
+
* findings the engine did not.
|
|
148
|
+
*/
|
|
149
|
+
export function blockingReviewComments(comments) {
|
|
150
|
+
return (comments ?? []).filter((comment) => comment.severity === 'blocker');
|
|
151
|
+
}
|
|
152
|
+
/** Whether any of `comments` is a `blocker` (see {@link blockingReviewComments}). */
|
|
153
|
+
export function hasBlockingReviewComments(comments) {
|
|
154
|
+
return (comments ?? []).some((comment) => comment.severity === 'blocker');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Whether a review raised anything it did NOT call a nit.
|
|
158
|
+
*
|
|
159
|
+
* What separates a batch worth sending back to the producer from one that only had polish to offer:
|
|
160
|
+
* a `minor` is stated to the reviewer as "never worth holding anything for", so a rule that spent a
|
|
161
|
+
* producer re-run plus a re-grading call on one would make that instruction false (kernel's
|
|
162
|
+
* `disposeCompanionVerdict` is the reader).
|
|
163
|
+
*
|
|
164
|
+
* Everything that is not the nit level counts, which puts an UNGRADED comment and a level this build
|
|
165
|
+
* has retired on the acting side. Both are cases where the urgency is unknown rather than known to
|
|
166
|
+
* be low, and the cheap error is one wasted round against a point silently dropped.
|
|
167
|
+
*/
|
|
168
|
+
export function hasReviewCommentsBeyondNits(comments) {
|
|
169
|
+
return (comments ?? []).some((comment) => comment.severity !== 'minor');
|
|
170
|
+
}
|
|
171
|
+
/** `comments` ordered worst severity first; an ungraded comment sorts last. Stable within a level. */
|
|
172
|
+
export function bySeverityWorstFirst(comments) {
|
|
173
|
+
return [...comments].sort((a, b) => reviewCommentSeverityRank(b.severity) - reviewCommentSeverityRank(a.severity));
|
|
174
|
+
}
|
|
62
175
|
/**
|
|
63
176
|
* The standardized, stored verdict a quality companion produced for an output it
|
|
64
177
|
* graded — shared by every companion site (the pipeline companion step and the
|
|
@@ -86,6 +199,10 @@ export const companionVerdictSchema = v.object({
|
|
|
86
199
|
* mirror-image reason — so it cannot regress on a point raised two rounds ago and forgotten.
|
|
87
200
|
*
|
|
88
201
|
* Absent on a round that anchored nothing, and on every verdict written before this existed.
|
|
202
|
+
*
|
|
203
|
+
* Their SEVERITIES are what makes the verdict self-describing: `passed: false` on a round whose
|
|
204
|
+
* rating cleared `threshold` is only readable next to the `blocker` that held it (see
|
|
205
|
+
* {@link reviewCommentSeveritySchema}).
|
|
89
206
|
*/
|
|
90
207
|
comments: v.optional(v.array(stepReviewCommentSchema)),
|
|
91
208
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-decisions.js","sourceRoot":"","sources":["../src/step-decisions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAErF,8EAA8E;AAC9E,mGAAmG;AACnG,oGAAoG;AACpG,wBAAwB;AACxB,EAAE;AACF,oGAAoG;AACpG,kGAAkG;AAClG,mGAAmG;AACnG,gGAAgG;AAChG,kGAAkG;AAClG,qFAAqF;AACrF,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC/B,CAAC,CAAA;AAGF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C;;;;OAIG;IACH,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAChC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAChC,gDAAgD;IAChD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAA;AAGF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,oEAAoE;IACpE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACxD,uDAAuD;IACvD,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3D,4CAA4C;IAC5C,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB
|
|
1
|
+
{"version":3,"file":"step-decisions.js","sourceRoot":"","sources":["../src/step-decisions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RunServiceScope } from './step-conditions.js';
|
|
1
2
|
import type { Block, Pipeline } from './entities.js';
|
|
2
3
|
/**
|
|
3
4
|
* The agent kind that drives a real browser against a running frontend and captures a
|
|
@@ -13,8 +14,30 @@ export declare const UI_TESTER_AGENT_KIND = "tester-ui";
|
|
|
13
14
|
export declare const VISUAL_CONFIRM_AGENT_KIND = "visual-confirmation";
|
|
14
15
|
/** The visual step kinds: a pipeline carrying any of these is a "visual" pipeline. */
|
|
15
16
|
export declare const VISUAL_STEP_KINDS: readonly ["tester-ui", "visual-confirmation"];
|
|
16
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Whether a pipeline includes any visual step (`tester-ui` / `visual-confirmation`) AT ALL,
|
|
19
|
+
* conditional ones included. The question for a caller asking whether the pipeline could ever
|
|
20
|
+
* drive a browser (run start resolves the frontend bindings off it). A caller deciding whether
|
|
21
|
+
* a pipeline may run HERE wants {@link pipelineRunsVisualStep} instead.
|
|
22
|
+
*/
|
|
17
23
|
export declare function pipelineHasVisualStep(pipeline: Pick<Pipeline, 'agentKinds'>): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a run of `scope` would actually REACH a visual step: the steps that are enabled and
|
|
26
|
+
* whose run condition (`stepOptions[i].condition`) the scope admits. This is the question the
|
|
27
|
+
* frame gate below has to ask, and it is NOT the same as "does the pipeline list one".
|
|
28
|
+
*
|
|
29
|
+
* Since the build ladder carries the CONDITIONAL tester pair, every build preset lists a
|
|
30
|
+
* `tester-ui` scoped to `serviceScope: 'frontend'`. On a backend service that step is skipped
|
|
31
|
+
* before it dispatches, so the pipeline demands no UI and the run starts fine — which is exactly
|
|
32
|
+
* what run admission concludes, filtering the chain through the same two rules before it reaches
|
|
33
|
+
* the frame gate. Asking the coarse question there instead hides every build rung from every
|
|
34
|
+
* picker on every non-frontend service.
|
|
35
|
+
*
|
|
36
|
+
* An UNRESOLVABLE scope (neither half set: a block under no service frame) admits every
|
|
37
|
+
* condition, the fail-safe direction `stepConditionSatisfied` takes throughout: the visual step
|
|
38
|
+
* would run, so the frame gate gets to refuse it rather than a condition quietly excusing it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function pipelineRunsVisualStep(pipeline: Pick<Pipeline, 'agentKinds' | 'enabled' | 'stepOptions'>, scope: RunServiceScope): boolean;
|
|
18
41
|
/**
|
|
19
42
|
* Whether a visual pipeline may run on a task under `frame`. A visual step needs a UI to
|
|
20
43
|
* exercise, which exists when the enclosing frame is either:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-pipeline.d.ts","sourceRoot":"","sources":["../src/visual-pipeline.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"visual-pipeline.d.ts","sourceRoot":"","sources":["../src/visual-pipeline.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAA0B,MAAM,sBAAsB,CAAA;AACnF,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAoBpD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAA;AAE/C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,wBAAwB,CAAA;AAE9D,sFAAsF;AACtF,eAAO,MAAM,iBAAiB,+CAA6D,CAAA;AAY3F;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,GAAG,OAAO,CAErF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,CAAC,EAClE,KAAK,EAAE,eAAe,GACrB,OAAO,CAOT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,SAAS,GAAG,IAAI,EACpD,MAAM,EAAE,SAAS,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,gBAAgB,CAAC,EAAE,GAClE,OAAO,CAWT;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,SAAS,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,gBAAgB,CAAC,EAAE,GAClE,MAAM,EAAE,CAcV"}
|
package/dist/visual-pipeline.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { resolveFrontendServePort } from './frontend.js';
|
|
2
|
+
import { stepConditionSatisfied } from './step-conditions.js';
|
|
2
3
|
// ---------------------------------------------------------------------------
|
|
3
4
|
// Visual-pipeline gating (shared by the SPA surface + the backend run-start gate).
|
|
4
5
|
//
|
|
5
6
|
// A "visual" pipeline exercises a rendered UI — it either drives a real browser
|
|
6
7
|
// against a running frontend (`tester-ui`) or parks for a human to review the
|
|
7
8
|
// captured screenshots vs the task's reference designs (`visual-confirmation`).
|
|
8
|
-
// Such a
|
|
9
|
+
// Such a step only makes sense where there IS a UI to exercise: a `frontend`
|
|
9
10
|
// frame (it owns the app under test), or a frame a `frontend` frame links to (the
|
|
10
11
|
// linked frontend is the UI a change to that service is validated through). The SPA
|
|
11
12
|
// uses these predicates to surface visual pipelines only where they can run; the
|
|
12
13
|
// backend gates a run start on the SAME rule so the guarantee holds server-side.
|
|
14
|
+
//
|
|
15
|
+
// What a pipeline LISTS and what a run REACHES are two questions, and the gate wants the
|
|
16
|
+
// second: a visual step scoped to a frontend service (`stepOptions[i].condition`) excuses
|
|
17
|
+
// itself from a backend run before it dispatches, which is what lets one build preset carry
|
|
18
|
+
// both testers. See `pipelineRunsVisualStep`.
|
|
13
19
|
// ---------------------------------------------------------------------------
|
|
14
20
|
/**
|
|
15
21
|
* The agent kind that drives a real browser against a running frontend and captures a
|
|
@@ -25,9 +31,44 @@ export const UI_TESTER_AGENT_KIND = 'tester-ui';
|
|
|
25
31
|
export const VISUAL_CONFIRM_AGENT_KIND = 'visual-confirmation';
|
|
26
32
|
/** The visual step kinds: a pipeline carrying any of these is a "visual" pipeline. */
|
|
27
33
|
export const VISUAL_STEP_KINDS = [UI_TESTER_AGENT_KIND, VISUAL_CONFIRM_AGENT_KIND];
|
|
28
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Whether an agent kind drives a rendered UI. Reads {@link VISUAL_STEP_KINDS} rather than
|
|
36
|
+
* re-spelling the disjunction, so a third visual kind added to that list is seen by both
|
|
37
|
+
* predicates below instead of leaving the frame gate quietly offering a UI-driving pipeline on a
|
|
38
|
+
* frame with no UI.
|
|
39
|
+
*/
|
|
40
|
+
function isVisualStepKind(kind) {
|
|
41
|
+
return VISUAL_STEP_KINDS.includes(kind);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether a pipeline includes any visual step (`tester-ui` / `visual-confirmation`) AT ALL,
|
|
45
|
+
* conditional ones included. The question for a caller asking whether the pipeline could ever
|
|
46
|
+
* drive a browser (run start resolves the frontend bindings off it). A caller deciding whether
|
|
47
|
+
* a pipeline may run HERE wants {@link pipelineRunsVisualStep} instead.
|
|
48
|
+
*/
|
|
29
49
|
export function pipelineHasVisualStep(pipeline) {
|
|
30
|
-
return pipeline.agentKinds.some(
|
|
50
|
+
return pipeline.agentKinds.some(isVisualStepKind);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Whether a run of `scope` would actually REACH a visual step: the steps that are enabled and
|
|
54
|
+
* whose run condition (`stepOptions[i].condition`) the scope admits. This is the question the
|
|
55
|
+
* frame gate below has to ask, and it is NOT the same as "does the pipeline list one".
|
|
56
|
+
*
|
|
57
|
+
* Since the build ladder carries the CONDITIONAL tester pair, every build preset lists a
|
|
58
|
+
* `tester-ui` scoped to `serviceScope: 'frontend'`. On a backend service that step is skipped
|
|
59
|
+
* before it dispatches, so the pipeline demands no UI and the run starts fine — which is exactly
|
|
60
|
+
* what run admission concludes, filtering the chain through the same two rules before it reaches
|
|
61
|
+
* the frame gate. Asking the coarse question there instead hides every build rung from every
|
|
62
|
+
* picker on every non-frontend service.
|
|
63
|
+
*
|
|
64
|
+
* An UNRESOLVABLE scope (neither half set: a block under no service frame) admits every
|
|
65
|
+
* condition, the fail-safe direction `stepConditionSatisfied` takes throughout: the visual step
|
|
66
|
+
* would run, so the frame gate gets to refuse it rather than a condition quietly excusing it.
|
|
67
|
+
*/
|
|
68
|
+
export function pipelineRunsVisualStep(pipeline, scope) {
|
|
69
|
+
return pipeline.agentKinds.some((kind, i) => isVisualStepKind(kind) &&
|
|
70
|
+
pipeline.enabled?.[i] !== false &&
|
|
71
|
+
stepConditionSatisfied(pipeline.stepOptions?.[i]?.condition, scope));
|
|
31
72
|
}
|
|
32
73
|
/**
|
|
33
74
|
* Whether a visual pipeline may run on a task under `frame`. A visual step needs a UI to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-pipeline.js","sourceRoot":"","sources":["../src/visual-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"visual-pipeline.js","sourceRoot":"","sources":["../src/visual-pipeline.ts"],"names":[],"mappings":"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"}
|