@intentius/chant 0.66.1 → 0.67.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/behaviour-engine.d.ts +212 -0
- package/dist/behaviour-engine.d.ts.map +1 -0
- package/dist/behaviour-http.d.ts +1 -1
- package/dist/behaviour-http.d.ts.map +1 -1
- package/dist/behaviour-kinds.d.ts +220 -0
- package/dist/behaviour-kinds.d.ts.map +1 -0
- package/dist/behaviour-predict.d.ts +83 -0
- package/dist/behaviour-predict.d.ts.map +1 -0
- package/dist/behaviour-request.d.ts +141 -0
- package/dist/behaviour-request.d.ts.map +1 -0
- package/dist/behaviour.d.ts +7 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +19 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +1 -1
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/predict-behaviour.d.ts +12 -5
- package/dist/op/activities/predict-behaviour.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/behaviour-delta.test.ts +8 -8
- package/src/behaviour-engine.ts +478 -0
- package/src/behaviour-http.ts +1 -1
- package/src/behaviour-kinds.test.ts +235 -0
- package/src/behaviour-kinds.ts +324 -0
- package/src/behaviour-predict.ts +253 -0
- package/src/behaviour-request.ts +294 -0
- package/src/behaviour.ts +7 -7
- package/src/cli/handlers/scenario.test.ts +1 -1
- package/src/cli/handlers/scenario.ts +1 -1
- package/src/index.ts +1 -0
- package/src/lexicon.ts +20 -0
- package/src/lifecycle/scenario-cost.test.ts +2 -2
- package/src/op/activities/index.ts +1 -2
- package/src/op/activities/predict-behaviour.test.ts +20 -7
- package/src/op/activities/predict-behaviour.ts +32 -30
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam between core and whatever answers its request (#2357),
|
|
3
|
+
* on the contract's transport (#2373, decided in #2359).
|
|
4
|
+
*
|
|
5
|
+
* `packages/core/src/behaviour.ts` says what a prediction may mean, how an
|
|
6
|
+
* absent engine must refuse, and — since #2359 — how a request reaches an
|
|
7
|
+
* engine: a `BehaviourTransport` carries the rendered request and brings back
|
|
8
|
+
* the engine's text or a finished refusal. This file adds what is core's on
|
|
9
|
+
* top of that and nothing more: the parse of a `behaviour/v1` answer, a command
|
|
10
|
+
* transport for an address that is a program on `PATH`, and the chooser that
|
|
11
|
+
* turns an address into one transport or the other.
|
|
12
|
+
*
|
|
13
|
+
* {@link BehaviourEngine} is what `./predict-behaviour.ts` talks to. It is
|
|
14
|
+
* one level above the transport — request in, parsed answer or refusal out —
|
|
15
|
+
* so the fixture engine in `__fixtures__` can be one without pretending to be
|
|
16
|
+
* a wire, and so `predict-behaviour.ts` never sees a byte. {@link
|
|
17
|
+
* transportEngine} is the only bridge between the two levels.
|
|
18
|
+
*
|
|
19
|
+
* ## The two transports
|
|
20
|
+
*
|
|
21
|
+
* A **URL** is dialled by core's `httpBehaviourTransport`
|
|
22
|
+
* (`packages/core/src/behaviour-http.ts`): `POST`, a bearer token from
|
|
23
|
+
* `CHANT_BEHAVIOUR_TOKEN` → `BEHAVIOUR_TOKEN`,
|
|
24
|
+
* and the status mapping the contract fixes. Nothing about that is core's,
|
|
25
|
+
* which is why it does not live here.
|
|
26
|
+
*
|
|
27
|
+
* A **command on PATH** is {@link commandTransport}, below: request on stdin,
|
|
28
|
+
* answer on stdout, no shell — a shell would make the address a
|
|
29
|
+
* code-execution surface for whatever set the variable. The child gets
|
|
30
|
+
* `behaviourEngineChildEnvironment()` and nothing else, for the reason given
|
|
31
|
+
* on that function: the request-side screen cannot see an inherited
|
|
32
|
+
* `process.env`. An engine that answered and still refused says so on stderr,
|
|
33
|
+
* and the words it uses pick the cause.
|
|
34
|
+
*
|
|
35
|
+
* ## A malformed answer is unreachable, not a report with holes
|
|
36
|
+
*
|
|
37
|
+
* Taking the fields that parsed and reporting the rest unpredicted would turn
|
|
38
|
+
* an engine emitting garbage into an estate that looks partly free — the
|
|
39
|
+
* failure the refusal arm exists to prevent, one level down. So the parse
|
|
40
|
+
* refuses whole, with a detail naming the entity and the field.
|
|
41
|
+
*
|
|
42
|
+
* With one exception, and it is the same rule the command transport applies
|
|
43
|
+
* to stderr: an engine that took the request, answered `200`, and wrote
|
|
44
|
+
* `{"error": "out of credit"}` has refused for a reason a status never
|
|
45
|
+
* carried. {@link transportEngine} reads that body's words after the parse
|
|
46
|
+
* has failed and never before, so an answer that priced the estate and
|
|
47
|
+
* declined one node "rate limit reached for this region" stays the report it
|
|
48
|
+
* is. Both transports reach the same three causes; only the evidence differs.
|
|
49
|
+
*/
|
|
50
|
+
import type { BehaviourBasis, BehaviourEngineEndpoint, BehaviourRefusalReport, BehaviourTransport, ResilienceVerdict } from "./behaviour.js";
|
|
51
|
+
import type { HttpBehaviourTransportDeps } from "./behaviour-http.js";
|
|
52
|
+
import type { EngineRequest } from "./behaviour-request.js";
|
|
53
|
+
/**
|
|
54
|
+
* The name a refusal is built under.
|
|
55
|
+
*
|
|
56
|
+
* It was the predicting lexicon's name while a lexicon predicted. Core
|
|
57
|
+
* predicts for the whole project since #2382, so there is no lexicon to scope
|
|
58
|
+
* the variable chain by: the chain is the chant-wide one, and this is the word
|
|
59
|
+
* a message uses for the thing that refused.
|
|
60
|
+
*/
|
|
61
|
+
export declare const BEHAVIOUR_SCOPE = "chant";
|
|
62
|
+
/** One entity's figures, as the engine states them. */
|
|
63
|
+
export interface EngineFigure {
|
|
64
|
+
perHour: number;
|
|
65
|
+
currency: string;
|
|
66
|
+
headroom: {
|
|
67
|
+
cpu?: number;
|
|
68
|
+
latency?: number;
|
|
69
|
+
};
|
|
70
|
+
errorRate: number;
|
|
71
|
+
resilience: {
|
|
72
|
+
failure: string;
|
|
73
|
+
verdict: ResilienceVerdict;
|
|
74
|
+
note?: string;
|
|
75
|
+
};
|
|
76
|
+
rightSize?: {
|
|
77
|
+
suggestion: string;
|
|
78
|
+
reason?: string;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** A run the engine answered. */
|
|
82
|
+
export interface EngineAnswer {
|
|
83
|
+
/** How the engine names itself, its version, and the tolerance it states. */
|
|
84
|
+
engine: string;
|
|
85
|
+
version: string;
|
|
86
|
+
tolerance: string;
|
|
87
|
+
basis: BehaviourBasis;
|
|
88
|
+
/** An estate total, when the engine states one of its own. Never chant's sum. */
|
|
89
|
+
total?: {
|
|
90
|
+
perHour: number;
|
|
91
|
+
currency: string;
|
|
92
|
+
};
|
|
93
|
+
/** Figures, keyed by the node name the request used. */
|
|
94
|
+
figures: Record<string, EngineFigure>;
|
|
95
|
+
/**
|
|
96
|
+
* Nodes the engine was sent and declined, keyed by name, with its reason.
|
|
97
|
+
* Separate from an absent key: a node in neither map is a defect, and
|
|
98
|
+
* `./predict-behaviour.ts` reports it rather than dropping it.
|
|
99
|
+
*/
|
|
100
|
+
declined?: Record<string, string>;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* What an engine call comes back with: a parsed answer, or a refusal built
|
|
104
|
+
* by whoever saw the failure — the transport for a wire condition, this file
|
|
105
|
+
* for an answer that does not parse. `./predict-behaviour.ts` returns the
|
|
106
|
+
* refusal as it stands and never rebuilds one, which is how the contract's
|
|
107
|
+
* four causes stay four remedies rather than one lexicon's guess.
|
|
108
|
+
*/
|
|
109
|
+
export type EngineOutcome = {
|
|
110
|
+
ok: true;
|
|
111
|
+
answer: EngineAnswer;
|
|
112
|
+
} | {
|
|
113
|
+
ok: false;
|
|
114
|
+
refusal: BehaviourRefusalReport;
|
|
115
|
+
};
|
|
116
|
+
/** Whatever answers a request, one level above the wire. The fixture engine is one of these. */
|
|
117
|
+
export interface BehaviourEngine {
|
|
118
|
+
predict(request: EngineRequest): Promise<EngineOutcome>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolve an address to an engine, or to `undefined` when nothing here
|
|
122
|
+
* speaks it. `env` is where a transport that authenticates reads its token
|
|
123
|
+
* from, and a chooser that has no use for it may ignore it. A caller that
|
|
124
|
+
* gets `undefined` refuses as `engine-unreachable` naming the address, which
|
|
125
|
+
* is the honest verdict for an address chant cannot dial.
|
|
126
|
+
*/
|
|
127
|
+
export type EngineConnect = (endpoint: BehaviourEngineEndpoint, env: Record<string, string | undefined>) => BehaviourEngine | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* A {@link BehaviourEngine} over a contract transport: render the request
|
|
130
|
+
* canonically, send it, parse what came back. The one bridge between the
|
|
131
|
+
* transport level and the engine level, so the parse runs on every wire and
|
|
132
|
+
* no transport gets its own.
|
|
133
|
+
*/
|
|
134
|
+
export declare function transportEngine(transport: BehaviourTransport, endpoint: BehaviourEngineEndpoint): BehaviourEngine;
|
|
135
|
+
/**
|
|
136
|
+
* A `command on PATH` address, run as a subprocess: the contract's
|
|
137
|
+
* `BehaviourTransport` for the third kind of address it names.
|
|
138
|
+
*
|
|
139
|
+
* The address is split on whitespace into a program and its arguments, which
|
|
140
|
+
* is the shape `CHANT_BEHAVIOUR_ENGINE="my-engine --model tiny"` produces.
|
|
141
|
+
* No shell: a shell would make the address a code-execution surface for
|
|
142
|
+
* whatever set the variable, and every argument the address needs can be
|
|
143
|
+
* written without one.
|
|
144
|
+
*/
|
|
145
|
+
export declare function commandTransport(endpoint: BehaviourEngineEndpoint): BehaviourTransport;
|
|
146
|
+
/** {@link commandTransport}, bridged to the engine level. */
|
|
147
|
+
export declare function commandEngine(endpoint: BehaviourEngineEndpoint): BehaviourEngine;
|
|
148
|
+
/**
|
|
149
|
+
* Everything wrong with one figure, as readable field paths. Empty means the
|
|
150
|
+
* figure is usable.
|
|
151
|
+
*
|
|
152
|
+
* Pure and exported so the shapes an engine can get wrong are testable without
|
|
153
|
+
* a subprocess. Every check here mirrors one `validateBehaviourBlock` applies
|
|
154
|
+
* downstream (`packages/core/src/behaviour.ts`) — the difference is *when*:
|
|
155
|
+
* that one throws, and a throw is the whole-lexicon failure `lexicon.ts`
|
|
156
|
+
* reserves for a live credential. A third party emitting one bad number is not
|
|
157
|
+
* that, and reporting it as that is how an operator goes looking for a leak.
|
|
158
|
+
*/
|
|
159
|
+
export declare function figureProblems(name: string, figure: unknown): string[];
|
|
160
|
+
/**
|
|
161
|
+
* What the parse of an engine's text comes to: the answer, or a detail
|
|
162
|
+
* naming what was wrong with it. Not a refusal yet — {@link transportEngine}
|
|
163
|
+
* builds that, with the endpoint the parse does not need to know.
|
|
164
|
+
*/
|
|
165
|
+
export type ParsedEngineAnswer = {
|
|
166
|
+
ok: true;
|
|
167
|
+
answer: EngineAnswer;
|
|
168
|
+
} | {
|
|
169
|
+
ok: false;
|
|
170
|
+
detail: string;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Parse an engine's text into an {@link EngineAnswer}.
|
|
174
|
+
*
|
|
175
|
+
* A malformed answer is `engine-unreachable` and not a report full of holes.
|
|
176
|
+
* The alternative — taking the fields that parsed and reporting the rest as
|
|
177
|
+
* unpredicted — would turn an engine emitting garbage into an estate that
|
|
178
|
+
* looks partially free, which is the failure the refusal arm exists to
|
|
179
|
+
* prevent, one level down.
|
|
180
|
+
*
|
|
181
|
+
* **Every figure is validated here, not only the envelope.** The first version
|
|
182
|
+
* of this function checked `engine`/`version`/`tolerance`/`basis` and that
|
|
183
|
+
* `figures` was an object, and then handed each figure's contents straight to
|
|
184
|
+
* `block()` in `./predict-behaviour.ts`, which dereferenced
|
|
185
|
+
* `figure.resilience.failure`. Seven malformed shapes were executed against
|
|
186
|
+
* it and all seven threw: three as bare `TypeError`s with no chant message,
|
|
187
|
+
* four through `validateBehaviourBlock` after the fact. A throw is the
|
|
188
|
+
* whole-lexicon failure `lexicon.ts` reserves for a live credential in the
|
|
189
|
+
* request, so a third-party engine emitting one bad number was indistinguishable
|
|
190
|
+
* from a leak — and the doc above claimed the opposite was happening.
|
|
191
|
+
*
|
|
192
|
+
* The detail names the entity and the field, because "the engine sent
|
|
193
|
+
* something wrong" is not a thing anybody can act on and "figures.web.headroom
|
|
194
|
+
* carries neither cpu nor latency" is. It flows into
|
|
195
|
+
* `unreachableBehaviourEngineRefusal`, which runs it through
|
|
196
|
+
* `scrubEngineDetail` and bounds it.
|
|
197
|
+
*/
|
|
198
|
+
export declare function parseEngineAnswer(text: string): ParsedEngineAnswer;
|
|
199
|
+
/**
|
|
200
|
+
* The transport chooser, with what the HTTP transport needs injectable.
|
|
201
|
+
*
|
|
202
|
+
* A `http://` or `https://` address gets core's `httpBehaviourTransport`,
|
|
203
|
+
* with its token read from `env` — the same `env` the address was read from,
|
|
204
|
+
* so a test drives both chains from one object. A bare address gets
|
|
205
|
+
* {@link commandTransport}. Any other scheme (`grpc://`, `unix://`) gets
|
|
206
|
+
* `undefined`, and the caller refuses naming the address: no transport here
|
|
207
|
+
* speaks it, and saying so beats a guess.
|
|
208
|
+
*/
|
|
209
|
+
export declare function connectWith(deps?: HttpBehaviourTransportDeps): EngineConnect;
|
|
210
|
+
/** The chooser the shipped plugin uses: the process's own `fetch`, the default deadline. */
|
|
211
|
+
export declare const defaultConnect: EngineConnect;
|
|
212
|
+
//# sourceMappingURL=behaviour-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behaviour-engine.d.ts","sourceRoot":"","sources":["../src/behaviour-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/behaviour-http.d.ts
CHANGED
|
@@ -68,7 +68,7 @@ export interface HttpBehaviourTransportDeps {
|
|
|
68
68
|
/** How long the engine has before it is treated as unreachable. */
|
|
69
69
|
timeoutMs?: number;
|
|
70
70
|
}
|
|
71
|
-
/** The default deadline: the same one
|
|
71
|
+
/** The default deadline: the same one the command transport gives a child. */
|
|
72
72
|
export declare const HTTP_BEHAVIOUR_TIMEOUT_MS = 30000;
|
|
73
73
|
/** True when an address is one this adapter dials. `grpc://` and friends are not. */
|
|
74
74
|
export declare function isHttpBehaviourAddress(value: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"behaviour-http.d.ts","sourceRoot":"","sources":["../src/behaviour-http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;AAGrB,sFAAsF;AACtF,MAAM,WAAW,0BAA0B;IACzC,oFAAoF;IACpF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,
|
|
1
|
+
{"version":3,"file":"behaviour-http.d.ts","sourceRoot":"","sources":["../src/behaviour-http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;AAGrB,sFAAsF;AACtF,MAAM,WAAW,0BAA0B;IACzC,oFAAoF;IACpF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAKhD,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,uBAAuB,EACjC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,sBAAsB,GAAG,SAAS,CAgCpC;AAQD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,uBAAuB,EACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,IAAI,GAAE,0BAA+B,GACpC,kBAAkB,CAoDpB"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an engine is asked to price, and who gets to say so (#2382).
|
|
3
|
+
*
|
|
4
|
+
* `./behaviour.ts` says what a prediction may mean and `./behaviour-http.ts`
|
|
5
|
+
* carries one to an engine. Between them sits a question neither answers: for
|
|
6
|
+
* a given entity in a project's graph, what *kind* of thing is it, and is it
|
|
7
|
+
* something an engine prices at all? #2357 answered it with one table in one
|
|
8
|
+
* lexicon, keyed by every other lexicon's entity types. That table described
|
|
9
|
+
* 117 types it did not own, and the capability rode on whether an optional
|
|
10
|
+
* package happened to be installed — which gave a consumer a fourth
|
|
11
|
+
* outcome this contract never named: no overlay, no refusal, and no reason.
|
|
12
|
+
*
|
|
13
|
+
* So the resolution lives here, where every other part of the feature already
|
|
14
|
+
* does, and the *rows* are contributed by the lexicon that owns the substrate.
|
|
15
|
+
* Core learns that an entity has an engine kind. It never learns which.
|
|
16
|
+
*
|
|
17
|
+
* ## Why rows are safe to make optional when the capability is not
|
|
18
|
+
*
|
|
19
|
+
* A lexicon that is not installed declared no entities of its types, so it has
|
|
20
|
+
* no rows to contribute and nothing goes missing: the estate simply contains
|
|
21
|
+
* nothing of that substrate. That is the opposite of the capability itself
|
|
22
|
+
* being optional, where an uninstalled package means an estate full of
|
|
23
|
+
* entities nobody will say anything about.
|
|
24
|
+
*
|
|
25
|
+
* ## The three things a lexicon can say about its own types
|
|
26
|
+
*
|
|
27
|
+
* - **mapped** — this type is a `compute`/`database`/`queue`, and its size
|
|
28
|
+
* is read from this declared property, in the provider's own vocabulary.
|
|
29
|
+
* - **declared unmapped** — this type is real and carries no rate an engine
|
|
30
|
+
* can quote, with the sentence saying why. A grant is not a resource; a
|
|
31
|
+
* boundary is not a node; a meter chant cannot read is not a figure.
|
|
32
|
+
* - **nothing priced** — nothing this lexicon declares is an estate an
|
|
33
|
+
* engine prices, once, for the whole substrate. A CI workflow is not an
|
|
34
|
+
* estate, and a policy language has nothing to saturate.
|
|
35
|
+
*
|
|
36
|
+
* A type a contributor claims and has no row for is `unknown-type`: the one
|
|
37
|
+
* verdict that is a defect rather than a decision, and the reason the three
|
|
38
|
+
* above are distinct states instead of one absent row.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* The categories a cost-and-saturation model actually distinguishes, not a
|
|
42
|
+
* taxonomy of every product a cloud sells.
|
|
43
|
+
*
|
|
44
|
+
* A kind is here when an engine would price it differently or when its
|
|
45
|
+
* saturation axis differs. `cache` is separate from `database` because a cache
|
|
46
|
+
* saturates on memory and a database on IO; `serverless` is separate from
|
|
47
|
+
* `compute` because one is priced per invocation and the other per hour of
|
|
48
|
+
* existence, and this contract's output shape is per hour. `control-plane` is
|
|
49
|
+
* separate from everything because a managed control plane is a flat hourly
|
|
50
|
+
* fee that does not move with the estate's traffic at all — pricing one as
|
|
51
|
+
* `compute` would make it look like something a right-size suggestion could
|
|
52
|
+
* shrink.
|
|
53
|
+
*/
|
|
54
|
+
export type EngineKind = "compute" | "serverless" | "control-plane" | "database" | "cache" | "queue" | "object-store" | "block-store" | "load-balancer" | "cdn";
|
|
55
|
+
/**
|
|
56
|
+
* Every legal {@link EngineKind}, derived from a total witness rather than
|
|
57
|
+
* written out by hand — the construction `behaviour.ts` uses for
|
|
58
|
+
* `BEHAVIOUR_BASES`, for the same reason: a hand-written array is checked for
|
|
59
|
+
* having legal members and never for having all of them.
|
|
60
|
+
*/
|
|
61
|
+
export declare const ENGINE_KINDS: readonly EngineKind[];
|
|
62
|
+
/** True when `value` is a legal {@link EngineKind}. */
|
|
63
|
+
export declare function isEngineKind(value: unknown): value is EngineKind;
|
|
64
|
+
/** One row of a lexicon's coverage: what one of its entity types becomes on the wire. */
|
|
65
|
+
export interface EngineKindMapping {
|
|
66
|
+
/** The engine-side kind. */
|
|
67
|
+
kind: EngineKind;
|
|
68
|
+
/**
|
|
69
|
+
* The substrate, as the engine names it — `aws`, `kubernetes`. A plain
|
|
70
|
+
* string rather than a closed union: the contributing lexicon names its own
|
|
71
|
+
* substrate, and core adding a member here for every lexicon that ships
|
|
72
|
+
* would be core holding the list it exists to stop holding.
|
|
73
|
+
*/
|
|
74
|
+
provider: string;
|
|
75
|
+
/**
|
|
76
|
+
* The declared property whose value is the entity's size, in the provider's
|
|
77
|
+
* own vocabulary — `InstanceType`, not a parsed vCPU count. Absent where the
|
|
78
|
+
* type has no size a single `size` string can carry.
|
|
79
|
+
*/
|
|
80
|
+
sizeProp?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Which type {@link sizeProp} holds. A value of the other type is absent
|
|
83
|
+
* rather than coerced: a number rendered into a size field an engine matches
|
|
84
|
+
* against a price table of strings is worse than no size at all.
|
|
85
|
+
*/
|
|
86
|
+
sizeType?: "string" | "number";
|
|
87
|
+
/**
|
|
88
|
+
* The declared property naming the region or zone this entity sits in, where
|
|
89
|
+
* the type states one of its own. Most do not, and inherit the caller's.
|
|
90
|
+
*/
|
|
91
|
+
regionProp?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* One lexicon's answer for its own entity types, contributed through the
|
|
95
|
+
* plugin's `behaviourKinds` field.
|
|
96
|
+
*
|
|
97
|
+
* Every field except {@link prefixes} is optional, and a lexicon that supplies
|
|
98
|
+
* only {@link nothingPriced} has said something complete: that none of what it
|
|
99
|
+
* declares is an estate an engine prices.
|
|
100
|
+
*/
|
|
101
|
+
export interface BehaviourKinds {
|
|
102
|
+
/** The substrate, as the engine names it. Every mapped row inherits it. */
|
|
103
|
+
provider: string;
|
|
104
|
+
/**
|
|
105
|
+
* The entity-type prefixes this lexicon owns — `["AWS::"]`, `["K8s::"]`.
|
|
106
|
+
* Ownership is what makes a missing row a defect rather than silence: a type
|
|
107
|
+
* nobody claims is nobody's mistake, and a type its own lexicon claims and
|
|
108
|
+
* cannot classify is a row somebody forgot to write.
|
|
109
|
+
*/
|
|
110
|
+
prefixes: readonly string[];
|
|
111
|
+
/** Types this lexicon prices, keyed by entity type — or by resolved type where {@link resolveType} is given. */
|
|
112
|
+
mapped?: Readonly<Record<string, Omit<EngineKindMapping, "provider"> & {
|
|
113
|
+
provider?: string;
|
|
114
|
+
}>>;
|
|
115
|
+
/** Types that are real and carry no rate, keyed the same way, with the sentence saying why. */
|
|
116
|
+
unmapped?: Readonly<Record<string, string>>;
|
|
117
|
+
/**
|
|
118
|
+
* Nothing this lexicon declares is priced, and this says why — checked
|
|
119
|
+
* before the tables, so a lexicon that states it needs no rows at all.
|
|
120
|
+
*/
|
|
121
|
+
nothingPriced?: string;
|
|
122
|
+
/**
|
|
123
|
+
* For a lexicon whose entities do not key rows by their entity type, the
|
|
124
|
+
* key to look rows up on instead. terraform's every `resource` block arrives
|
|
125
|
+
* as `Terraform::Resource`, and what an engine would price is the type its
|
|
126
|
+
* address carries.
|
|
127
|
+
*
|
|
128
|
+
* It is handed the entity type as well as the props, because a lexicon
|
|
129
|
+
* usually redirects only *some* of its types: terraform's root blocks
|
|
130
|
+
* (`Terraform::Variable`, `Terraform::Output`) key by entity type like
|
|
131
|
+
* everyone else, and only `Terraform::Resource` reads its key out of the
|
|
132
|
+
* props. Returning the entity type unchanged is how a contributor says "this
|
|
133
|
+
* one is ordinary". Returning `undefined` is "nothing to look up", the same
|
|
134
|
+
* no-opinion an unseen type gets.
|
|
135
|
+
*/
|
|
136
|
+
resolveType?: (entityType: string, props: Record<string, unknown> | undefined) => string | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* A family of this lexicon's types that belongs to a substrate nothing here
|
|
139
|
+
* models, named as the substrate — or `undefined` to let the type carry on
|
|
140
|
+
* to {@link unmappedWhen}. terraform is the case this exists for: one
|
|
141
|
+
* lexicon's `resource` blocks span every provider there is, so `google_`
|
|
142
|
+
* and `azurerm_` and `null_` are each a boundary of their own, while an
|
|
143
|
+
* `aws_` type with no row stays the defect it is. A contributor whose whole
|
|
144
|
+
* substrate is unpriced uses {@link nothingPriced} instead; this is for the
|
|
145
|
+
* lexicon that models part of what it declares.
|
|
146
|
+
*/
|
|
147
|
+
notModelledWhen?: (type: string) => string | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* A last word on a type this lexicon claims and has no row for: the reason
|
|
150
|
+
* it is unmapped, or `undefined` to leave it a defect. CloudFormation's
|
|
151
|
+
* property types are the case this exists for — hundreds of nested blocks
|
|
152
|
+
* that became entities of their own, never separately priced, and
|
|
153
|
+
* enumerating them one row at a time would bury the table's real decisions.
|
|
154
|
+
*/
|
|
155
|
+
unmappedWhen?: (type: string) => string | undefined;
|
|
156
|
+
}
|
|
157
|
+
/** What one entity type resolves to. Total: every type reaches exactly one of these. */
|
|
158
|
+
export type CoverageVerdict = {
|
|
159
|
+
status: "mapped";
|
|
160
|
+
mapping: EngineKindMapping;
|
|
161
|
+
} | {
|
|
162
|
+
status: "declared-unmapped";
|
|
163
|
+
reason: string;
|
|
164
|
+
} | {
|
|
165
|
+
status: "provider-not-modelled";
|
|
166
|
+
substrate: string;
|
|
167
|
+
} | {
|
|
168
|
+
status: "unknown-type";
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Resolve one entity type against the contributed rows.
|
|
172
|
+
*
|
|
173
|
+
* Total by construction: every type reaches one of the four states and there
|
|
174
|
+
* is no fifth arm for "dropped". That is the property the request builder
|
|
175
|
+
* relies on to guarantee every entity it was asked about lands in `entities`
|
|
176
|
+
* or in `unpredicted`.
|
|
177
|
+
*
|
|
178
|
+
* `hasOwnProperty` rather than a truthiness check, because these are plain
|
|
179
|
+
* object literals and an entity named after a prototype member would otherwise
|
|
180
|
+
* resolve to a mapping that does not exist.
|
|
181
|
+
*/
|
|
182
|
+
export declare function coverageFor(contributors: readonly BehaviourKinds[], entityType: string, props?: Record<string, unknown>): CoverageVerdict;
|
|
183
|
+
/**
|
|
184
|
+
* The contributor that owns an entity type, or `undefined` when nobody claims
|
|
185
|
+
* it. Exported because a caller that has already resolved a verdict often
|
|
186
|
+
* needs the owner too — to name it in a detail, or to label the entity the way
|
|
187
|
+
* its own lexicon would.
|
|
188
|
+
*/
|
|
189
|
+
export declare function ownerOf(contributors: readonly BehaviourKinds[], entityType: string): BehaviourKinds | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* How a detail names an entity's kind. The chant entity type, except where the
|
|
192
|
+
* owning lexicon keys its rows on something else: `Terraform::Resource` names
|
|
193
|
+
* nothing a reader can act on, and the provider type is the kind, so the label
|
|
194
|
+
* is `aws_vpc (Terraform::Resource)`.
|
|
195
|
+
*/
|
|
196
|
+
export declare function coverageLabel(contributors: readonly BehaviourKinds[], entityType: string, props?: Record<string, unknown>): string;
|
|
197
|
+
/**
|
|
198
|
+
* The `detail` an `unpredicted` entry carries, naming the kind in every case.
|
|
199
|
+
*
|
|
200
|
+
* The kind is named here, in the per-entity decline, because that is the only
|
|
201
|
+
* place in this contract with a per-entity axis: a `BehaviourRefusalReport` is
|
|
202
|
+
* a statement about the whole run and has no `entities` key by design, so a
|
|
203
|
+
* report-level refusal for one unmapped bucket would take the other nineteen
|
|
204
|
+
* entities' figures down with it.
|
|
205
|
+
*
|
|
206
|
+
* The `unknown-type` arm names the lexicon that owns the type rather than a
|
|
207
|
+
* file path, because since #2382 the row belongs to whichever lexicon defines
|
|
208
|
+
* the type, and that is the thing a reader needs to be told.
|
|
209
|
+
*/
|
|
210
|
+
export declare function unmappedDetail(label: string, verdict: CoverageVerdict, owner?: BehaviourKinds): string;
|
|
211
|
+
/**
|
|
212
|
+
* Compare two strings by UTF-16 code unit.
|
|
213
|
+
*
|
|
214
|
+
* Not `localeCompare`, which reads the ambient locale: under `sv-SE` and
|
|
215
|
+
* `et-EE` it orders these type names differently from `en-US`, which would
|
|
216
|
+
* make the request's bytes — and therefore any golden fixture, and therefore
|
|
217
|
+
* any declared-versus-live delta — a function of the machine that built them.
|
|
218
|
+
*/
|
|
219
|
+
export declare const byCodeUnit: (a: string, b: string) => number;
|
|
220
|
+
//# sourceMappingURL=behaviour-kinds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behaviour-kinds.d.ts","sourceRoot":"","sources":["../src/behaviour-kinds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `predictBehaviour()` — the fourth
|
|
3
|
+
* observation method (#2357, contract #2356).
|
|
4
|
+
*
|
|
5
|
+
* The whole method is four moves, in this order, and the order is the contract:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Screen the request.** `screenBehaviourRequest` and nothing else. It is
|
|
8
|
+
* the only entry point, and calling `assertNoCredentialInOptions` instead
|
|
9
|
+
* applies one rule of three — that was review finding F1 on #2365, where a
|
|
10
|
+
* `ghp_…` past the walk's depth budget and an `awsSecretAccessKey` in
|
|
11
|
+
* `props` both went out with the request.
|
|
12
|
+
* 2. **Resolve the engine.** `behaviourEngineFrom`, walking
|
|
13
|
+
* `CHANT_BEHAVIOUR_ENGINE_BEHAVIOUR_SCOPE` → `CHANT_BEHAVIOUR_ENGINE` →
|
|
14
|
+
* `BEHAVIOUR_ENGINE`. Nothing named means `noBehaviourEngineRefusal`, and
|
|
15
|
+
* it happens **before** anything is priced: a lexicon that prices first and
|
|
16
|
+
* checks the engine afterwards has already decided what zero means.
|
|
17
|
+
* 3. **Build the request.** `buildEngineRequest`, offline and pure
|
|
18
|
+
* (`./request.ts`).
|
|
19
|
+
* 4. **Ask, and translate the answer.** One {@link EngineOutcome} onto the
|
|
20
|
+
* contract's builders. A refusal comes back from the transport already
|
|
21
|
+
* built — the contract's transport (#2373) names the condition and the
|
|
22
|
+
* variable where the wire was seen — and is returned as it stands; this
|
|
23
|
+
* file holds no switch over causes. No figure is ever computed here either:
|
|
24
|
+
* this file has no arithmetic on money in it at all, and that is not an
|
|
25
|
+
* accident. The epic's first rule is that a missing engine produces a
|
|
26
|
+
* refusal and "never a locally faked number", and the surest way to keep
|
|
27
|
+
* that true is for the code that would have faked it not to exist.
|
|
28
|
+
*
|
|
29
|
+
* ## Every entity lands somewhere
|
|
30
|
+
*
|
|
31
|
+
* `behaviourReport` refuses a report that leaves a name in neither map, so the
|
|
32
|
+
* loop below has no `continue` that drops one. Four ways an entity can end up
|
|
33
|
+
* unpredicted, and each names a different thing:
|
|
34
|
+
*
|
|
35
|
+
* | Outcome | Reason | Means |
|
|
36
|
+
* |---|---|---|
|
|
37
|
+
* | the coverage table declares it unmapped | `unsupported-kind` | chant looked, and this kind has no rate |
|
|
38
|
+
* | the coverage table has never seen it | `unsupported-kind` | chant has not looked; the detail says so and where to add the row |
|
|
39
|
+
* | the engine declined it | `read-failed` | chant asked and the engine could not answer |
|
|
40
|
+
* | the engine answered about neither | `read-failed` | the engine lost it, and this says so rather than hiding it |
|
|
41
|
+
*
|
|
42
|
+
* The last row is the one that would otherwise be silent. An engine that
|
|
43
|
+
* returns figures for eleven of twelve nodes and mentions the twelfth nowhere
|
|
44
|
+
* is a bug in the engine, and an estate that quietly renders eleven nodes is
|
|
45
|
+
* how it stays a bug.
|
|
46
|
+
*/
|
|
47
|
+
import { type BehaviourResult, type PredictBehaviourOptions } from "./behaviour.js";
|
|
48
|
+
import type { BehaviourKinds } from "./behaviour-kinds.js";
|
|
49
|
+
import { BEHAVIOUR_SCOPE, type EngineConnect } from "./behaviour-engine.js";
|
|
50
|
+
export { BEHAVIOUR_SCOPE };
|
|
51
|
+
/** What {@link createBehaviourPredict} needs that the method's own options do not carry. */
|
|
52
|
+
export interface BehaviourPredictDeps {
|
|
53
|
+
/**
|
|
54
|
+
* The coverage rows to resolve entity types against — every configured
|
|
55
|
+
* lexicon's `behaviourKinds`, in the order the plugins were loaded.
|
|
56
|
+
*
|
|
57
|
+
* An empty list is legal and means every declared entity is withheld as
|
|
58
|
+
* `unknown-type`: nothing has said what any of them are. That is a report
|
|
59
|
+
* about an estate nobody has rows for, not a refusal, because the engine was
|
|
60
|
+
* reachable and answered; the distinction is the whole point of the refusal
|
|
61
|
+
* arm.
|
|
62
|
+
*/
|
|
63
|
+
kinds?: readonly BehaviourKinds[];
|
|
64
|
+
/** The environment the engine address is resolved from. Defaults to the process's. */
|
|
65
|
+
env?: Record<string, string | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* How an address becomes an engine. Defaults to `./behaviour-engine.ts`'s chooser,
|
|
68
|
+
* which dials a URL through core's HTTP transport and a bare address as a
|
|
69
|
+
* command on PATH.
|
|
70
|
+
*/
|
|
71
|
+
connect?: EngineConnect;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build core's `predictBehaviour`, with the environment and the
|
|
75
|
+
* transport injected.
|
|
76
|
+
*
|
|
77
|
+
* Injected rather than read from module scope so a test can drive the whole
|
|
78
|
+
* method — screen, resolve, serialize, translate — against a fixture engine
|
|
79
|
+
* without touching `process.env`, which is what the shared conformance suite's
|
|
80
|
+
* probes need in order to ask the same request twice and compare.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createBehaviourPredict(deps?: BehaviourPredictDeps): (options: PredictBehaviourOptions) => Promise<BehaviourResult>;
|
|
83
|
+
//# sourceMappingURL=behaviour-predict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behaviour-predict.d.ts","sourceRoot":"","sources":["../src/behaviour-predict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAG7B,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAkB,KAAK,aAAa,EAAqB,MAAM,oBAAoB,CAAC;AAE5G,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,4FAA4F;AAC5F,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,sFAAsF;IACtF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,oBAAyB,GAC9B,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,eAAe,CAAC,CA0FhE"}
|