@qontinui/shared-types 2.2.0 → 2.3.1

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.
@@ -0,0 +1,95 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated.
4
+ * DO NOT MODIFY IT BY HAND. Regenerate with
5
+ * `qontinui-runner/src-tauri/scripts/generate_types.sh`.
6
+ */
7
+
8
+ import type { BoundKind } from "./BoundKind";
9
+ import type { FilterNarrowing } from "./FilterNarrowing";
10
+
11
+ /**
12
+ * The envelope keys every bounded read serves beside its own collection key
13
+ * (plan `2026-09-05-every-bounded-read-is-a-page-that-reads-as-a-corpus`,
14
+ * §3 Layer 2).
15
+ *
16
+ * **Every key is ALWAYS present, and `null` is a value here, not an
17
+ * absence.** This deliberately departs from the crate's
18
+ * `skip_serializing_if = "Option::is_none"` convention: `total: null` says "no
19
+ * count ran", `truncated: null` says "unknown", and `next_cursor: null` says
20
+ * "there is no next page" — each a positive statement a reader must be able
21
+ * to see, not a key it might be missing because of an older server.
22
+ *
23
+ * Enforced on all three sides, because an absent key that silently reads as
24
+ * `null` is exactly the "absent is UNKNOWN, never a default" defect:
25
+ * serialization never skips a field; every `Option` field carries
26
+ * `#[schemars(required, schema_with = "nullable::<T>")]` — `required` because
27
+ * schemars 1 otherwise omits an `Option` from `required` (the generated
28
+ * Pydantic model would then default a missing key to `None`), and
29
+ * `schema_with` because `required` alone makes schemars emit the INNER type's
30
+ * schema, dropping `null` so generated models reject the value this wire
31
+ * sends; and deserialization uses `Option::deserialize`, which refuses a
32
+ * MISSING key instead of defaulting it (serde's derive otherwise treats an
33
+ * absent `Option` as `None`). Pinning tests assert, structurally, that
34
+ * `required` is exactly the field set and that every nullable key admits
35
+ * `null`.
36
+ *
37
+ * `count` and `limit` keep the spellings list doors already serve (coord
38
+ * #1897 put `count` on every agent list door; web proxies and runner pollers
39
+ * read both), so merging this into an existing response rewrites them with
40
+ * the same values rather than moving them.
41
+ */
42
+ export interface BoundedReadMeta {
43
+ /**
44
+ * `false` ONLY when the store is unprovisioned: an empty page with
45
+ * `available: false` is UNKNOWN, not "nothing matched".
46
+ */
47
+ available: boolean;
48
+ /**
49
+ * Which kind of bound produced `total` / `truncated`.
50
+ */
51
+ bound_kind: BoundKind;
52
+ /**
53
+ * Rows in this page (the legacy spelling of `shown`).
54
+ */
55
+ count: number;
56
+ /**
57
+ * For a relevance-RANKED read, which can never hand out a cursor: the
58
+ * door that enumerates the same corpus by an immutable sort key (plan
59
+ * `2026-09-05-every-bounded-read-is-a-page-that-reads-as-a-corpus` D8), so
60
+ * a `truncated: true, next_cursor: null` answer still says how to reach
61
+ * the rest. `null` on a keyset walk, whose `next_cursor` is the way on.
62
+ */
63
+ enumerate_via: string | null;
64
+ /**
65
+ * A FILTER the surface narrowed before the read ran, or `null`.
66
+ */
67
+ filter_narrowed: FilterNarrowing | null;
68
+ /**
69
+ * The cap actually applied to this page.
70
+ */
71
+ limit: number;
72
+ /**
73
+ * The opaque token for the next page — pass it back verbatim as
74
+ * `cursor`. `null` iff `truncated` is not `true`, OR the read is a
75
+ * RANKING that cannot be paged — then `truncated` may be `true` with
76
+ * `next_cursor: null`, and `enumerate_via` names the door that walks the
77
+ * corpus by an immutable key.
78
+ */
79
+ next_cursor: string | null;
80
+ /**
81
+ * Rows in this page.
82
+ */
83
+ shown: number;
84
+ /**
85
+ * The exact match count from this page's start position — a number only
86
+ * when `bound_kind` is `exact`, else `null`.
87
+ */
88
+ total: number | null;
89
+ /**
90
+ * Whether matching rows exist beyond this page; `null` when
91
+ * `bound_kind` is `unknown`.
92
+ */
93
+ truncated: boolean | null;
94
+ [k: string]: unknown;
95
+ }
@@ -0,0 +1,25 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated.
4
+ * DO NOT MODIFY IT BY HAND. Regenerate with
5
+ * `qontinui-runner/src-tauri/scripts/generate_types.sh`.
6
+ */
7
+
8
+ /**
9
+ * Three-valued capability fact.
10
+ *
11
+ * `Unknown` is the default for anything a profile or catalog does not state.
12
+ * It is a distinct value from `Unsupported` on purpose: a boolean cannot
13
+ * represent "we never asked", and coercing that to "no" silently disables
14
+ * working capabilities.
15
+ *
16
+ * Moved here from qontinui-runner `src-tauri/src/model_catalog.rs` so the
17
+ * model/API layer (`ModelFacts`) and the CLI-session layer ([`CliProfile`])
18
+ * speak one tri-state; `model_catalog` re-exports it. Serialized as
19
+ * `"supported"` / `"unsupported"` / `"unknown"`.
20
+ *
21
+ * [`CapabilityState::Unknown`] must never be a reason to strip content or
22
+ * refuse a route. Callers that must act on an unknown fact should attempt the
23
+ * capability and let the backend be the authority.
24
+ */
25
+ export type CapabilityState = "supported" | "unsupported" | "unknown";
@@ -0,0 +1,492 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated.
4
+ * DO NOT MODIFY IT BY HAND. Regenerate with
5
+ * `qontinui-runner/src-tauri/scripts/generate_types.sh`.
6
+ */
7
+
8
+ import type { CapabilityState } from "./CapabilityState";
9
+
10
+ /**
11
+ * How one account's CLI state is kept apart from another's.
12
+ *
13
+ * Wire shape (internally tagged with `"kind"`):
14
+ * - `{ "kind": "env_var", "name": "CLAUDE_CONFIG_DIR" }`
15
+ * - `{ "kind": "home_dir" }` / `{ "kind": "none" }` / `{ "kind": "unknown" }`
16
+ */
17
+ export type AccountIsolation =
18
+ | {
19
+ kind: "env_var";
20
+ /**
21
+ * The variable's name (`"CLAUDE_CONFIG_DIR"`).
22
+ */
23
+ name: string;
24
+ [k: string]: unknown;
25
+ }
26
+ | {
27
+ kind: "home_dir";
28
+ [k: string]: unknown;
29
+ }
30
+ | {
31
+ kind: "none";
32
+ [k: string]: unknown;
33
+ }
34
+ | {
35
+ kind: "unknown";
36
+ [k: string]: unknown;
37
+ };
38
+ /**
39
+ * One way a CLI can be authenticated.
40
+ *
41
+ * Wire shape (internally tagged with `"kind"`):
42
+ * - `{ "kind": "cli_login", "args": ["login"] }`
43
+ * - `{ "kind": "api_key_env", "vars": ["OPENAI_API_KEY"] }`
44
+ *
45
+ * No `unknown` arm: an unknown auth story is an empty
46
+ * [`CliProfile::auth`] list.
47
+ */
48
+ export type AuthMethod =
49
+ | {
50
+ /**
51
+ * Arguments after the program (`["login"]`, or `["/login"]` typed in
52
+ * the TUI).
53
+ */
54
+ args: string[];
55
+ kind: "cli_login";
56
+ [k: string]: unknown;
57
+ }
58
+ | {
59
+ kind: "api_key_env";
60
+ /**
61
+ * Variable names, in the CLI's precedence order.
62
+ */
63
+ vars: string[];
64
+ [k: string]: unknown;
65
+ };
66
+ /**
67
+ * How the CLI is launched without per-tool approval prompts.
68
+ *
69
+ * Wire shape (internally tagged with `"kind"`):
70
+ * - `{ "kind": "flags", "argv": ["--permission-mode", "bypassPermissions"],
71
+ * "detect": ["--dangerously-skip-permissions", "bypassPermissions"] }`
72
+ * - `{ "kind": "none" }` / `{ "kind": "unknown" }`
73
+ */
74
+ export type AutoApprove =
75
+ | {
76
+ /**
77
+ * The flags the runner appends to enable auto-approval.
78
+ */
79
+ argv: string[];
80
+ /**
81
+ * Tokens whose presence on an existing argv means auto-approval is
82
+ * already on — every spelling the CLI accepts, not only the one the
83
+ * runner writes.
84
+ */
85
+ detect: string[];
86
+ kind: "flags";
87
+ [k: string]: unknown;
88
+ }
89
+ | {
90
+ kind: "none";
91
+ [k: string]: unknown;
92
+ }
93
+ | {
94
+ kind: "unknown";
95
+ [k: string]: unknown;
96
+ };
97
+ /**
98
+ * How the runner asks a live session to exit cleanly.
99
+ *
100
+ * Wire shape (internally tagged with `"kind"`):
101
+ * - `{ "kind": "typed_command", "text": "/exit" }`
102
+ * - `{ "kind": "signal" }` / `{ "kind": "unknown" }`
103
+ *
104
+ * `Unknown` means the runner must type nothing and report that it could not
105
+ * exit the session gracefully.
106
+ */
107
+ export type GracefulExit =
108
+ | {
109
+ kind: "typed_command";
110
+ /**
111
+ * The command text (`"/exit"`).
112
+ */
113
+ text: string;
114
+ [k: string]: unknown;
115
+ }
116
+ | {
117
+ kind: "signal";
118
+ [k: string]: unknown;
119
+ }
120
+ | {
121
+ kind: "unknown";
122
+ [k: string]: unknown;
123
+ };
124
+ /**
125
+ * How the runner learns a CLI session's id.
126
+ *
127
+ * Wire shape (internally tagged with `"kind"`):
128
+ * - `{ "kind": "pinned", "flag": "--session-id" }`
129
+ * - `{ "kind": "read_back", "capture": "codex_session_file" }`
130
+ * - `{ "kind": "unknown" }`
131
+ */
132
+ export type IdentitySource =
133
+ | {
134
+ /**
135
+ * The flag that takes the id (`"--session-id"`).
136
+ */
137
+ flag: string;
138
+ kind: "pinned";
139
+ [k: string]: unknown;
140
+ }
141
+ | {
142
+ /**
143
+ * Name of the runner capture mechanism that recovers the id
144
+ * (`"codex_session_file"`). The mechanism itself is runner behaviour.
145
+ */
146
+ capture: string;
147
+ kind: "read_back";
148
+ [k: string]: unknown;
149
+ }
150
+ | {
151
+ kind: "unknown";
152
+ [k: string]: unknown;
153
+ };
154
+ /**
155
+ * What a restore of a CLI's session can honestly bring back.
156
+ *
157
+ * Serialized in the coord wire spelling the runner's `RestoreTier::wire_str`
158
+ * already uses: `"full"` / `"terminal_only"`.
159
+ *
160
+ * Defaults to `TerminalOnly` — the conservative claim: a profile that has not
161
+ * established resume must not promise the conversation back.
162
+ */
163
+ export type RestoreTier = "full" | "terminal_only";
164
+ /**
165
+ * How a session is resumed by id.
166
+ *
167
+ * Wire shape (internally tagged with `"kind"`):
168
+ * - `{ "kind": "by_id_argv", "template": ["claude", "--resume", "{id}"] }`
169
+ * - `{ "kind": "none" }` / `{ "kind": "unknown" }`
170
+ */
171
+ export type ResumeSpec =
172
+ | {
173
+ kind: "by_id_argv";
174
+ /**
175
+ * The argv template (`["codex", "resume", "{id}"]`).
176
+ */
177
+ template: string[];
178
+ [k: string]: unknown;
179
+ }
180
+ | {
181
+ kind: "none";
182
+ [k: string]: unknown;
183
+ }
184
+ | {
185
+ kind: "unknown";
186
+ [k: string]: unknown;
187
+ };
188
+ /**
189
+ * The machine-readable protocol a CLI offers besides its TUI.
190
+ *
191
+ * Wire shape (internally tagged with `"kind"` so an arm can gain data, e.g.
192
+ * an adapter command for `acp`, without a breaking change):
193
+ * `{ "kind": "claude_stream_json" }`, `{ "kind": "codex_app_server" }`,
194
+ * `{ "kind": "acp" }`, `{ "kind": "none" }`, `{ "kind": "unknown" }`.
195
+ */
196
+ export type StructuredLane =
197
+ | {
198
+ kind: "claude_stream_json";
199
+ [k: string]: unknown;
200
+ }
201
+ | {
202
+ kind: "codex_app_server";
203
+ [k: string]: unknown;
204
+ }
205
+ | {
206
+ kind: "acp";
207
+ [k: string]: unknown;
208
+ }
209
+ | {
210
+ kind: "none";
211
+ [k: string]: unknown;
212
+ }
213
+ | {
214
+ kind: "unknown";
215
+ [k: string]: unknown;
216
+ };
217
+ /**
218
+ * Where the CLI writes its conversation transcript.
219
+ *
220
+ * Wire shape (internally tagged with `"kind"`):
221
+ * - `{ "kind": "jsonl_under_config_dir", "subdir": "projects" }`
222
+ * - `{ "kind": "session_file_glob", "glob": ".codex/sessions/** /rollout-*.jsonl" }`
223
+ * - `{ "kind": "none" }` / `{ "kind": "unknown" }`
224
+ */
225
+ export type TranscriptSpec =
226
+ | {
227
+ kind: "jsonl_under_config_dir";
228
+ /**
229
+ * Subdirectory of the config dir holding transcripts (`"projects"`).
230
+ */
231
+ subdir: string;
232
+ [k: string]: unknown;
233
+ }
234
+ | {
235
+ /**
236
+ * The glob (`".codex/sessions/** /rollout-*.jsonl"`).
237
+ */
238
+ glob: string;
239
+ kind: "session_file_glob";
240
+ [k: string]: unknown;
241
+ }
242
+ | {
243
+ kind: "none";
244
+ [k: string]: unknown;
245
+ }
246
+ | {
247
+ kind: "unknown";
248
+ [k: string]: unknown;
249
+ };
250
+ /**
251
+ * Whether the CLI stops on a folder-trust prompt at first launch in a
252
+ * directory.
253
+ *
254
+ * Wire shape (internally tagged with `"kind"`):
255
+ * - `{ "kind": "prompt", "markers": ["Do you trust the files in this folder?"], "accept": "1" }`
256
+ * - `{ "kind": "none" }` / `{ "kind": "unknown" }`
257
+ */
258
+ export type TrustDialog =
259
+ | {
260
+ /**
261
+ * The keystroke text that accepts it (sent followed by Enter).
262
+ */
263
+ accept: string;
264
+ kind: "prompt";
265
+ /**
266
+ * Case-insensitive substrings that identify the prompt on the
267
+ * ANSI-stripped screen.
268
+ */
269
+ markers: string[];
270
+ [k: string]: unknown;
271
+ }
272
+ | {
273
+ kind: "none";
274
+ [k: string]: unknown;
275
+ }
276
+ | {
277
+ kind: "unknown";
278
+ [k: string]: unknown;
279
+ };
280
+
281
+ /**
282
+ * Everything the runner needs to know about one AI CLI's session behaviour.
283
+ *
284
+ * One instance per CLI (`claude`, `codex`, …), built by the runner as static
285
+ * data and served to the frontend (`GET /terminals/cli-profiles`, Tauri
286
+ * command `terminal_cli_profiles`) so no consumer holds a second copy.
287
+ *
288
+ * Every fact that can be unverified defaults to its `Unknown` arm; see the
289
+ * module docs. Scraped facts ([`Self::handshake`], [`Self::usage_limit_phrases`],
290
+ * [`TrustDialog::Prompt`]) break when the CLI changes its screens, which is
291
+ * why [`Self::verified_version`] records the CLI version they were verified
292
+ * against.
293
+ */
294
+ export interface CliProfile {
295
+ /**
296
+ * How one account's CLI state is kept apart from another's.
297
+ */
298
+ accountIsolation?: AccountIsolation & {};
299
+ /**
300
+ * The ways the CLI can be authenticated. Empty means none are recorded —
301
+ * UNKNOWN, not "needs no authentication".
302
+ */
303
+ auth: AuthMethod[];
304
+ /**
305
+ * How the CLI is launched without per-tool approval prompts, and how an
306
+ * existing argv is recognised as already doing so.
307
+ */
308
+ autoApprove?: AutoApprove & {};
309
+ /**
310
+ * Human-readable name for launch menus and zone labels (`"Claude Code"`).
311
+ */
312
+ displayName: string;
313
+ /**
314
+ * How the runner asks a live session to exit cleanly.
315
+ */
316
+ gracefulExit?: GracefulExit & {};
317
+ /**
318
+ * On-screen markers that decide whether a resume succeeded or failed.
319
+ */
320
+ handshake?: HandshakePatterns & {};
321
+ /**
322
+ * Stable provider id (`"claude"`, `"codex"`). The same string the runner
323
+ * stores as a terminal session record's `provider`.
324
+ */
325
+ id: string;
326
+ /**
327
+ * How the runner learns the CLI's session id.
328
+ */
329
+ identity?: IdentitySource & {};
330
+ /**
331
+ * Per-OS install commands, shown beside a disabled launch entry when the
332
+ * CLI's binary is absent.
333
+ */
334
+ install?: InstallCommands & {};
335
+ /**
336
+ * Free-form caveats a reader should see beside the profile (e.g. "macOS:
337
+ * same code path, unverified on hardware").
338
+ */
339
+ notes?: string[];
340
+ /**
341
+ * Arguments that make the structured lane hand each tool approval to the
342
+ * runner as a typed permission request instead of deciding it itself
343
+ * (`["--permission-prompt-tool", "stdio"]`), verified against
344
+ * [`Self::verified_version`]. Rendered only for a launch that asks to be
345
+ * prompted, and never beside an auto-approve flag. Empty means no such
346
+ * arguments are known, so a prompted structured launch is not offered.
347
+ */
348
+ permissionPromptArgs?: string[];
349
+ /**
350
+ * Program stems that identify this CLI on an argv head or in a process
351
+ * census, without directory or extension (`["claude"]`). Matching strips
352
+ * the path and a Windows `.exe`/`.cmd` suffix before comparing.
353
+ */
354
+ programs: string[];
355
+ /**
356
+ * Arguments the runner appends to every PTY-hosted (interactive TUI)
357
+ * launch of this CLI, verified against [`Self::verified_version`]
358
+ * (`["--teammate-mode", "in-process"]`, which keeps Claude Code agent
359
+ * teams inside the session instead of splitting the caller's tmux window).
360
+ * Empty means none.
361
+ */
362
+ ptyArgs?: string[];
363
+ /**
364
+ * Whether the structured lane emits a typed rate-limit event.
365
+ */
366
+ rateLimitEvent?: CapabilityState & string;
367
+ /**
368
+ * What a restore of this CLI's session can honestly bring back.
369
+ */
370
+ restoreTier?: RestoreTier & string;
371
+ /**
372
+ * How a session is resumed by id.
373
+ */
374
+ resume?: ResumeSpec & {};
375
+ /**
376
+ * Other spellings the CLI accepts for the resume flag of
377
+ * [`ResumeSpec::ByIdArgv`] (`["-r"]`). Matched only as a whole argv
378
+ * token followed by the id, and only when the argv's program is this
379
+ * CLI: a short flag like `-r` means something else to most programs.
380
+ * Empty means none are known.
381
+ */
382
+ resumeFlagAliases?: string[];
383
+ /**
384
+ * Argv tokens, besides the identity flag, the resume flag and its
385
+ * aliases, by which the user picks the session themselves
386
+ * (`["--continue", "-c"]` — continue the most recent session). Any of
387
+ * them on a launch means the runner must not pin an id of its own. A token
388
+ * matches a whole argv entry case-insensitively; a `--long` token also
389
+ * matches `--long=…`. Empty means none are known.
390
+ */
391
+ sessionChoiceArgs?: string[];
392
+ /**
393
+ * The machine-readable protocol the CLI offers besides its TUI.
394
+ */
395
+ structuredLane?: StructuredLane & {};
396
+ /**
397
+ * Where the CLI writes its conversation transcript.
398
+ */
399
+ transcript?: TranscriptSpec & {};
400
+ /**
401
+ * Whether the CLI stops on a folder-trust prompt at first launch in a
402
+ * directory, and how to recognise and answer it.
403
+ */
404
+ trustDialog?: TrustDialog & {};
405
+ /**
406
+ * Whether the structured lane emits an explicit end-of-turn event.
407
+ */
408
+ turnBoundaryEvent?: CapabilityState & string;
409
+ /**
410
+ * Whether the structured lane delivers a typed permission request (a
411
+ * tool-use approval the runner answers) rather than bypassing approval.
412
+ */
413
+ typedPermission?: CapabilityState & string;
414
+ /**
415
+ * Case-insensitive phrases the CLI paints when an account's usage limit
416
+ * is reached. A grid match is a `Hint`-confidence
417
+ * [`FailureKind::QuotaExhausted`] signal, never a confirmed one. Empty
418
+ * means no phrases are known.
419
+ */
420
+ usageLimitPhrases: string[];
421
+ /**
422
+ * CLI version the scraped facts in this profile were verified against
423
+ * (`"2.1.285"`). `None` means no version was recorded — treat every
424
+ * scraped fact as unverified.
425
+ */
426
+ verifiedVersion?: string | null;
427
+ [k: string]: unknown;
428
+ }
429
+ /**
430
+ * On-screen markers that decide whether a resume succeeded or failed.
431
+ *
432
+ * Substring lists match the ANSI-stripped screen case-insensitively; regex
433
+ * lists are compiled by BOTH the Rust `regex` crate and JavaScript `RegExp`,
434
+ * so a pattern must stay in the syntax both engines accept (no look-around,
435
+ * no backreferences, no named-group syntax that differs between them).
436
+ *
437
+ * Regex sources are ALWAYS matched case-insensitively, like the substrings:
438
+ * each engine compiles them with its own case-insensitive switch (Rust
439
+ * `RegexBuilder::case_insensitive`, the JavaScript `i` flag). A source must
440
+ * therefore not carry inline flags such as `(?i)`, which JavaScript rejects.
441
+ *
442
+ * All body lists empty means no markers are known, and a resume cannot be
443
+ * verified from the screen.
444
+ */
445
+ export interface HandshakePatterns {
446
+ /**
447
+ * Substrings whose presence means the resume failed.
448
+ */
449
+ failure: string[];
450
+ /**
451
+ * Regex sources (matched case-insensitively) whose match means the
452
+ * resume failed.
453
+ */
454
+ failureRegex: string[];
455
+ /**
456
+ * Substrings whose presence means the resumed session came up.
457
+ */
458
+ success: string[];
459
+ /**
460
+ * Regex sources (matched case-insensitively) whose match means the
461
+ * resumed session came up.
462
+ */
463
+ successRegex: string[];
464
+ /**
465
+ * Regex sources (matched case-insensitively) matched against the pane's
466
+ * CURRENT window title only, never its body, whose match means the
467
+ * resumed session came up. A title the CLI sets at launch is evidence the
468
+ * body cannot fake, provided the pattern is anchored to the CLI's own
469
+ * title (the shell titles the window too). Empty means none are known.
470
+ */
471
+ titleRegex?: string[];
472
+ [k: string]: unknown;
473
+ }
474
+ /**
475
+ * Per-OS install commands for a CLI. `None` for an OS means no command is
476
+ * recorded for it.
477
+ */
478
+ export interface InstallCommands {
479
+ /**
480
+ * Install command on Linux (`"npm i -g @openai/codex"`).
481
+ */
482
+ linux?: string | null;
483
+ /**
484
+ * Install command on macOS.
485
+ */
486
+ macos?: string | null;
487
+ /**
488
+ * Install command on Windows.
489
+ */
490
+ windows?: string | null;
491
+ [k: string]: unknown;
492
+ }
@@ -0,0 +1,35 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated.
4
+ * DO NOT MODIFY IT BY HAND. Regenerate with
5
+ * `qontinui-runner/src-tauri/scripts/generate_types.sh`.
6
+ */
7
+
8
+ /**
9
+ * A FILTER the surface narrowed before running the read — reported, never
10
+ * applied silently, because a narrowed filter that reads as a complete answer
11
+ * is the same defect class as a silent empty.
12
+ *
13
+ * Promoted from `coord.findings`' `resource_keys_truncated`, the only
14
+ * narrowing any surface reported when this type was written: a list-valued
15
+ * filter truncated at a cap rather than refused (truncating a FILTER only
16
+ * narrows a read). Minimal on purpose — which parameter, how many values
17
+ * were actually applied, and the cap that dropped the rest. A caller seeing
18
+ * it knows a miss is meaningless for the values beyond the cap.
19
+ */
20
+ export interface FilterNarrowing {
21
+ /**
22
+ * How many values of it the read actually applied.
23
+ */
24
+ applied: number;
25
+ /**
26
+ * The cap the surface enforces; values past it were dropped.
27
+ */
28
+ cap: number;
29
+ /**
30
+ * The query parameter that was narrowed, spelled as the caller spelled it
31
+ * on the wire (e.g. `resource_keys`).
32
+ */
33
+ parameter: string;
34
+ [k: string]: unknown;
35
+ }