@vibe-agent-toolkit/cli 0.2.0-rc.4 → 0.2.0-rc.5
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/bin.js +35 -2
- package/dist/bin.js.map +1 -1
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +23 -5
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/claude/plugin/install.js +0 -1
- package/dist/commands/claude/plugin/install.js.map +1 -1
- package/dist/commands/corpus/runner.d.ts.map +1 -1
- package/dist/commands/corpus/runner.js +1 -19
- package/dist/commands/corpus/runner.js.map +1 -1
- package/dist/commands/inventory.js +1 -1
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/resources/check-progress.d.ts +145 -0
- package/dist/commands/resources/check-progress.d.ts.map +1 -0
- package/dist/commands/resources/check-progress.js +205 -0
- package/dist/commands/resources/check-progress.js.map +1 -0
- package/dist/commands/resources/check-supervisor.d.ts +465 -0
- package/dist/commands/resources/check-supervisor.d.ts.map +1 -0
- package/dist/commands/resources/check-supervisor.js +566 -0
- package/dist/commands/resources/check-supervisor.js.map +1 -0
- package/dist/commands/resources/check.d.ts +454 -0
- package/dist/commands/resources/check.d.ts.map +1 -0
- package/dist/commands/resources/check.js +1237 -0
- package/dist/commands/resources/check.js.map +1 -0
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +277 -6
- package/dist/commands/resources/index.js.map +1 -1
- package/dist/commands/resources/query.d.ts +89 -0
- package/dist/commands/resources/query.d.ts.map +1 -0
- package/dist/commands/resources/query.js +146 -0
- package/dist/commands/resources/query.js.map +1 -0
- package/dist/commands/resources/scan.js +1 -1
- package/dist/commands/resources/scan.js.map +1 -1
- package/dist/commands/skills/install.js +0 -1
- package/dist/commands/skills/install.js.map +1 -1
- package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
- package/dist/commands/skills/skill-discovery.js +4 -2
- package/dist/commands/skills/skill-discovery.js.map +1 -1
- package/dist/utils/agent-runner.d.ts.map +1 -1
- package/dist/utils/agent-runner.js +7 -3
- package/dist/utils/agent-runner.js.map +1 -1
- package/dist/utils/command-error.d.ts +56 -1
- package/dist/utils/command-error.d.ts.map +1 -1
- package/dist/utils/command-error.js +66 -3
- package/dist/utils/command-error.js.map +1 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +10 -3
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/issue-severity.d.ts +12 -5
- package/dist/utils/issue-severity.d.ts.map +1 -1
- package/dist/utils/issue-severity.js +1 -1
- package/dist/utils/issue-severity.js.map +1 -1
- package/dist/utils/projection-query.d.ts +263 -0
- package/dist/utils/projection-query.d.ts.map +1 -0
- package/dist/utils/projection-query.js +262 -0
- package/dist/utils/projection-query.js.map +1 -0
- package/dist/utils/projection-store.d.ts +104 -2
- package/dist/utils/projection-store.d.ts.map +1 -1
- package/dist/utils/projection-store.js +126 -4
- package/dist/utils/projection-store.js.map +1 -1
- package/dist/utils/vat-bin-path.d.ts +36 -0
- package/dist/utils/vat-bin-path.d.ts.map +1 -0
- package/dist/utils/vat-bin-path.js +49 -0
- package/dist/utils/vat-bin-path.js.map +1 -0
- package/package.json +25 -14
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vat resources check` — run the project's own SQL assertions over its
|
|
3
|
+
* resource projection.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this verb exists when `vat resources query` already runs SQL
|
|
6
|
+
*
|
|
7
|
+
* A query answers a question once. A question worth asking twice is a rule, and
|
|
8
|
+
* a rule that lives in someone's shell history is not enforced — it decays into
|
|
9
|
+
* a comment. This verb runs the statements a project wrote into
|
|
10
|
+
* `resources.checks`, turns each violating row into an ordinary validation
|
|
11
|
+
* finding, and exits non-zero when any of them is an error. That is the whole
|
|
12
|
+
* difference, and it is the difference between a tool and a gate.
|
|
13
|
+
*
|
|
14
|
+
* ## 🔑 A broken check is an ERROR, never a skip
|
|
15
|
+
*
|
|
16
|
+
* VAT ships no schema version, so a renamed column simply breaks a check's SQL.
|
|
17
|
+
* The tempting handling — log it and carry on — is the one thing this must never
|
|
18
|
+
* do: a check that stopped running looks exactly like a check that passed, and
|
|
19
|
+
* the project keeps reporting green over an assertion nobody is making any more.
|
|
20
|
+
* So a statement that will not run is reported as a finding at **error**
|
|
21
|
+
* severity, with the columns the projection actually has, and it fails the run.
|
|
22
|
+
*
|
|
23
|
+
* That report carries its OWN code (`RESOURCE_CHECK_BROKEN`), which no
|
|
24
|
+
* `validation.severity` entry can reach. A check's severity override is about how
|
|
25
|
+
* bad a VIOLATION is; while the two shared the code `CUSTOM:<name>`, the
|
|
26
|
+
* documented way to stand down an inherited check also silenced the news that it
|
|
27
|
+
* had stopped checking. See the `catch` in `runChecks`.
|
|
28
|
+
*
|
|
29
|
+
* ## 🔑 An empty CORPUS is a refusal too, not a pass
|
|
30
|
+
*
|
|
31
|
+
* The same class one level further out, and the one that shipped. `checksRun` is
|
|
32
|
+
* the denominator of RULES; nothing counted the ROWS, so a repository whose
|
|
33
|
+
* enumeration came back empty — a broad `.gitignore`, a shallow or sparse CI
|
|
34
|
+
* checkout, a root that resolved somewhere else — ran every declared check over
|
|
35
|
+
* nothing and reported `status: success` on exit 0 with empty stderr. Population
|
|
36
|
+
* declines ignored members rather than flagging them, so the tables held no
|
|
37
|
+
* trace of it either.
|
|
38
|
+
*
|
|
39
|
+
* So the population's size is published (`membersEnumerated`), and a run whose
|
|
40
|
+
* checks executed over zero members is an ERROR under the same non-overridable
|
|
41
|
+
* code as a broken statement — see {@link emptyCorpusFinding}. A gate that
|
|
42
|
+
* asserts nothing over nothing has not passed.
|
|
43
|
+
*
|
|
44
|
+
* ## 🔑 An unknown `--check` name is a refusal, not an empty pass
|
|
45
|
+
*
|
|
46
|
+
* The same failure class one flag over: a filter that matched nothing ran nothing
|
|
47
|
+
* and exited 0. `requireDeclaredCheck` refuses it before the crawl, naming the
|
|
48
|
+
* declared set. A gate that cannot fail is worse than no gate.
|
|
49
|
+
*
|
|
50
|
+
* ## 🔑 SQL is the surface a user OPTED IN to, so no BUILT-IN check may be SQL
|
|
51
|
+
*
|
|
52
|
+
* Every check this verb runs is adopter-declared: {@link checkCommand} reads
|
|
53
|
+
* `config?.resources?.checks` and nothing else, and warns loudly when a project
|
|
54
|
+
* declares none. There are no built-ins, and the one way to end that quietly is
|
|
55
|
+
* to author the first one as SQL. A default-on rule written as a statement makes
|
|
56
|
+
* the engine, the projection and the population mandatory for everyone who
|
|
57
|
+
* inherits it, without anybody deciding that. So: **built-ins are TypeScript
|
|
58
|
+
* predicates over the projection's row model.** SQL stays the two places a user
|
|
59
|
+
* asked for it — this verb's declared checks, and `vat resources query`.
|
|
60
|
+
*
|
|
61
|
+
* ⚠️ The engine today is `node:sqlite`, built into Node, so the thing at stake is
|
|
62
|
+
* not an install — it is the POPULATION. On an ~11,700-member adopter tree
|
|
63
|
+
* building the projection is **>99.9%** of a check run (16.5 s cold, ~1.3 s from
|
|
64
|
+
* the store) against **0.0008–0.004 s** for the statements themselves; see
|
|
65
|
+
* `vat-knowledge-resources.md`, which carries that measurement. That is exactly
|
|
66
|
+
* the cost "What this does NOT do" below refuses to put on every adopter's
|
|
67
|
+
* pre-commit path, and a default-on SQL check would put it there without the
|
|
68
|
+
* decision. The INSTALL cost is deferred rather than gone: the open question
|
|
69
|
+
* about a columnar engine is a 108 MB platform binding on a published toolkit,
|
|
70
|
+
* and this invariant is what keeps that question still answerable either way.
|
|
71
|
+
*
|
|
72
|
+
* ## 🔑 The DEFAULT check set belongs to the pipeline, not to the config file
|
|
73
|
+
*
|
|
74
|
+
* A directory with no `vibe-agent-toolkit.config.yaml` must run exactly the same
|
|
75
|
+
* default-on checks as one with a config; config only ADDS to that set or
|
|
76
|
+
* OVERRIDES a severity in it. This is load-bearing rather than a convenience:
|
|
77
|
+
* *"'default-on error' is meaningless as a category if being default-on requires
|
|
78
|
+
* a config file to say so."*
|
|
79
|
+
*
|
|
80
|
+
* It is therefore a constraint on WHERE the defaults live in code, not only on
|
|
81
|
+
* what they are. They cannot be defaulted into the parsed config object, because
|
|
82
|
+
* an absent config is `undefined` and every default would vanish with it — for
|
|
83
|
+
* the project that never wrote one, which is the population the category exists
|
|
84
|
+
* for. The rest of VAT already behaves this way and is the shape to match:
|
|
85
|
+
* `vat audit` completes its entire scan first and reads config only to apply
|
|
86
|
+
* severity overrides, warning and CONTINUING when the file cannot be read; and
|
|
87
|
+
* `loadResourcesWithConfig` hands `vat resources validate` a registry whose
|
|
88
|
+
* built-in validators run whether `loadConfig` returned a config or nothing.
|
|
89
|
+
* This verb has no defaults yet, so the invariant is a rule for the first one —
|
|
90
|
+
* and the day it is written is the easiest day to break it.
|
|
91
|
+
*
|
|
92
|
+
* ## Keeping a TypeScript check and its SQL twin: two good reasons, one trap
|
|
93
|
+
*
|
|
94
|
+
* The proposal was "write the predicate twice, in TypeScript and in SQL, and run
|
|
95
|
+
* whichever is faster". Two thirds of it are worth having.
|
|
96
|
+
*
|
|
97
|
+
* ✅ **As documentation.** An SQL twin is executable documentation of the row
|
|
98
|
+
* model, and strictly better than prose about it: prose can describe a column
|
|
99
|
+
* that no longer exists and never say so, while a statement stops compiling —
|
|
100
|
+
* which this verb reports as `RESOURCE_CHECK_BROKEN` rather than as a skip.
|
|
101
|
+
*
|
|
102
|
+
* ✅ **As a differential oracle.** Run both over the frozen corpus and assert
|
|
103
|
+
* IDENTICAL findings. That is the only thing which makes a dual implementation
|
|
104
|
+
* better than a single one rather than worse: two implementations with no
|
|
105
|
+
* mandatory differential test are simply two places for one rule to be wrong.
|
|
106
|
+
* Apply it selectively, to genuinely relational checks — done by default, every
|
|
107
|
+
* new rule costs three artifacts instead of one.
|
|
108
|
+
*
|
|
109
|
+
* ⛔ **As a runtime optimizer — rejected, on two INDEPENDENT grounds.** It would
|
|
110
|
+
* essentially never choose SQL: `buildResourceProjection` hands the rows back in
|
|
111
|
+
* memory before the ephemeral database exists at all, so the TypeScript arm is a
|
|
112
|
+
* for-loop over data already in hand, and the SQL arm's whole measured share of a
|
|
113
|
+
* run is the 0.0008–0.004 s above. A scheduler would be choosing between two
|
|
114
|
+
* arms of the 0.1%. And it reintroduces the dependency through the back door: an
|
|
115
|
+
* optimizer that MAY choose SQL means SQL MAY be needed at check time, which for
|
|
116
|
+
* anyone shipping the thing is the same as needed. **Optionality is not a
|
|
117
|
+
* property you can keep while also letting a scheduler reach for the optional
|
|
118
|
+
* thing.**
|
|
119
|
+
*
|
|
120
|
+
* ## 🔑 Adopter SQL runs UNSANDBOXED on purpose — and contributed SQL is not adopter SQL
|
|
121
|
+
*
|
|
122
|
+
* What a statement may BE is gated hard, and documented where it is enforced:
|
|
123
|
+
* `assertIsQuery` and `detachForeignSchemas` in
|
|
124
|
+
* `packages/projection-sqlite/src/store.ts` refuse `ATTACH` and `PRAGMA`, with
|
|
125
|
+
* the measured cross-repository leak that motivated both, and CHANGELOG.md's
|
|
126
|
+
* `--budget` entry carries why nothing inside this process can interrupt a
|
|
127
|
+
* runaway statement. Read those; do not restate them here.
|
|
128
|
+
*
|
|
129
|
+
* What is written down nowhere else is that everything PAST those gates is
|
|
130
|
+
* unsandboxed deliberately. A `.sql` file the adopter points their own config at
|
|
131
|
+
* is adopter code, at the same trust boundary as their eslint config: they wrote
|
|
132
|
+
* it or they chose to inherit it, and VAT is not the thing standing between a
|
|
133
|
+
* project and its own repository.
|
|
134
|
+
*
|
|
135
|
+
* 🚨 That reasoning covers exactly ONE trust domain, and the rule scoping it is
|
|
136
|
+
* the other half: **contributed SQL is a reviewed EXAMPLE, never an
|
|
137
|
+
* auto-executed check.** A contribution channel is third-party text, and a
|
|
138
|
+
* statement arriving through one has none of the "they chose it" the paragraph
|
|
139
|
+
* above rests on. Ship it as documentation an adopter copies into their own
|
|
140
|
+
* `resources.checks` deliberately. One paragraph must not be stretched to cover
|
|
141
|
+
* both domains.
|
|
142
|
+
*
|
|
143
|
+
* ## What this does NOT do
|
|
144
|
+
*
|
|
145
|
+
* It does not fold into `vat resources validate`. That command is on every
|
|
146
|
+
* adopter's pre-commit path, and adding a store-backed population to it is a
|
|
147
|
+
* cost and a risk that deserves its own decision with its own evidence. Wiring
|
|
148
|
+
* this into CI is one line in a workflow; making it unavoidable is not this
|
|
149
|
+
* change's call to make.
|
|
150
|
+
*/
|
|
151
|
+
import { type ResourceCheck } from '@vibe-agent-toolkit/resources';
|
|
152
|
+
import { type ValidationIssue } from '@vibe-agent-toolkit/schema';
|
|
153
|
+
import { type SeverityOverrides } from '../../utils/issue-severity.js';
|
|
154
|
+
import { type Logger } from '../../utils/logger.js';
|
|
155
|
+
import { type AskProjection, type PopulationExtent, type ProjectionProvenance } from '../../utils/projection-query.js';
|
|
156
|
+
import { type ProgressEntry } from './check-progress.js';
|
|
157
|
+
import { type AbnormalDeath } from './check-supervisor.js';
|
|
158
|
+
/**
|
|
159
|
+
* Where a supervised run announces what it is doing, one unit at a time.
|
|
160
|
+
*
|
|
161
|
+
* A plain callback rather than the writer itself, so the loop knows nothing
|
|
162
|
+
* about files: the unit suite hands it an array, the supervised child hands it
|
|
163
|
+
* {@link createProgressWriter}'s append, and `--budget 0` hands it nothing.
|
|
164
|
+
*/
|
|
165
|
+
export type ProgressSink = (entry: ProgressEntry) => void;
|
|
166
|
+
interface CheckOptions {
|
|
167
|
+
debug?: boolean;
|
|
168
|
+
/** Run only this check, by its config key. */
|
|
169
|
+
check?: string;
|
|
170
|
+
/** `yaml` (default) or `json`. Same document either way. */
|
|
171
|
+
format?: string;
|
|
172
|
+
/**
|
|
173
|
+
* How long the run may go WITHOUT completing a unit of work, in seconds.
|
|
174
|
+
* `0` removes the bound and keeps everything in this process.
|
|
175
|
+
*/
|
|
176
|
+
budget?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Hidden. Where to append progress — and, by its mere presence, the
|
|
179
|
+
* instruction to do the work here rather than supervise a child that does.
|
|
180
|
+
* Set by {@link childArgs} and by nothing else; an operator passing it by hand
|
|
181
|
+
* gets an unsupervised run and a log file, which is harmless.
|
|
182
|
+
*/
|
|
183
|
+
costLog?: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* What one declared check cost, and what it found.
|
|
187
|
+
*
|
|
188
|
+
* ## 🚨 The population is charged to NOBODY, and that is deliberate
|
|
189
|
+
*
|
|
190
|
+
* {@link durationMs} is the STATEMENT alone. The git tracker, the projection
|
|
191
|
+
* build and the load into the ephemeral database happen ONCE and serve every
|
|
192
|
+
* check in the run, so folding that shared setup into each rule would make N
|
|
193
|
+
* cheap rules look expensive and make the per-rule numbers sum to N times a cost
|
|
194
|
+
* paid once. It is published separately instead — `populationSecs` beside
|
|
195
|
+
* `population` in the document — so a reader can reconcile the parts against
|
|
196
|
+
* `durationSecs` rather than inferring the remainder and attributing it to
|
|
197
|
+
* whichever rule they happen to be reading.
|
|
198
|
+
*
|
|
199
|
+
* 🪤 This repo has already shipped the opposite mistake once, in another
|
|
200
|
+
* instrument: `parse ab` reported a pooled arm BACKWARDS because its estimate
|
|
201
|
+
* was thread-summed, and the report surfaced no caveat that would have told the
|
|
202
|
+
* reader. A shared cost silently attributed to one participant is the same
|
|
203
|
+
* defect wearing different clothes. If you ever want the population inside these
|
|
204
|
+
* numbers, divide it out explicitly and say so in the field name.
|
|
205
|
+
*/
|
|
206
|
+
export interface CheckCost {
|
|
207
|
+
/** The check's key in `resources.checks`. */
|
|
208
|
+
readonly name: string;
|
|
209
|
+
/** Wall time of this check's statement, and of nothing it shares with others. */
|
|
210
|
+
readonly durationMs: number;
|
|
211
|
+
/** Rows the statement returned — the violations it selected. Absent when the statement did not run. */
|
|
212
|
+
readonly rows?: number;
|
|
213
|
+
/** Set when the statement threw. A statement that did not complete has no row count. */
|
|
214
|
+
readonly broken?: true;
|
|
215
|
+
}
|
|
216
|
+
/** What one run of the checks produced. */
|
|
217
|
+
interface CheckOutcome extends ProjectionProvenance, PopulationExtent {
|
|
218
|
+
issues: readonly ValidationIssue[];
|
|
219
|
+
/**
|
|
220
|
+
* One record per check that actually ran — the denominator every count below
|
|
221
|
+
* is read against, and what each of them cost.
|
|
222
|
+
*
|
|
223
|
+
* 🔑 A LIST rather than a count beside a list. `checksRun` used to be carried
|
|
224
|
+
* separately and is now derived from `costs.length`, because two numbers that
|
|
225
|
+
* must agree are a drift bug with no gate on it: nothing fails when a new
|
|
226
|
+
* `continue` skips the record but not the counter, and the document then
|
|
227
|
+
* reports a denominator no published entry accounts for.
|
|
228
|
+
*/
|
|
229
|
+
costs: readonly CheckCost[];
|
|
230
|
+
}
|
|
231
|
+
export interface CheckPayloadInput extends CheckOutcome {
|
|
232
|
+
root: string;
|
|
233
|
+
durationMs: number;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Build the check report.
|
|
237
|
+
*
|
|
238
|
+
* Pure: no file system, no clock, no `process.exit` — the same contract every
|
|
239
|
+
* other payload builder here follows, so the document's shape stays under unit
|
|
240
|
+
* test rather than only under a CLI spawn.
|
|
241
|
+
*
|
|
242
|
+
* `checksRun` is published beside the counts and is not decoration: zero
|
|
243
|
+
* findings from four checks and zero findings from **no** checks are the same
|
|
244
|
+
* document without it, and they mean opposite things. A project whose config key
|
|
245
|
+
* is misspelled would otherwise read as passing. It is DERIVED from the `checks`
|
|
246
|
+
* list rather than carried alongside it, so the denominator and the entries that
|
|
247
|
+
* account for it cannot disagree.
|
|
248
|
+
*
|
|
249
|
+
* 🚨 `populationSecs` and the per-check `durationSecs` do not overlap and do not
|
|
250
|
+
* sum to `durationSecs`. The population is paid once and shared by every check;
|
|
251
|
+
* see {@link CheckCost} for why it is charged to none of them.
|
|
252
|
+
*
|
|
253
|
+
* @param input - The findings and the provenance of the run behind them
|
|
254
|
+
* @returns The document to serialize
|
|
255
|
+
*/
|
|
256
|
+
export declare function buildCheckOutputData(input: CheckPayloadInput): Record<string, unknown>;
|
|
257
|
+
/**
|
|
258
|
+
* Refuse a `--check` name the project does not declare.
|
|
259
|
+
*
|
|
260
|
+
* 🔑 **An unknown name used to be a silent green.** The filter was a bare
|
|
261
|
+
* `if (only !== undefined && name !== only) continue;` and nothing compared the
|
|
262
|
+
* flag against the declared keys, so `--check nope` filtered every check away,
|
|
263
|
+
* ran none, and exited 0 with `checksRun: 0` and `issues: []` on empty stderr.
|
|
264
|
+
* The loud "no checks are declared" warning never fired, because it asks whether
|
|
265
|
+
* the `checks` MAP is empty, never whether the FILTER matched anything.
|
|
266
|
+
*
|
|
267
|
+
* That is not a hypothetical typo: `vat resources check --check orphan-skills`
|
|
268
|
+
* is the example in this command's own help text. Rename or delete that check
|
|
269
|
+
* and the CI step keeps passing forever while asserting nothing.
|
|
270
|
+
*
|
|
271
|
+
* Thrown rather than reported as a finding, because it is an OPERATOR error and
|
|
272
|
+
* not a content violation — the two have different exit codes in this command's
|
|
273
|
+
* contract (2 versus 1) and different audiences. Thrown before the projection is
|
|
274
|
+
* populated, so a mistyped flag costs no crawl.
|
|
275
|
+
*
|
|
276
|
+
* @param checks - The project's `resources.checks`
|
|
277
|
+
* @param only - The `--check` value, or undefined
|
|
278
|
+
* @throws When `only` names no declared check
|
|
279
|
+
*/
|
|
280
|
+
export declare function requireDeclaredCheck(checks: Readonly<Record<string, ResourceCheck>>, only: string | undefined): void;
|
|
281
|
+
/**
|
|
282
|
+
* Name every `CUSTOM:` severity override that overrides nothing.
|
|
283
|
+
*
|
|
284
|
+
* 🔑 **The same silent-green shape as an unknown `--check` name, one surface
|
|
285
|
+
* over.** {@link requireDeclaredCheck} refuses `--check nope` because a filter
|
|
286
|
+
* that matched nothing ran nothing and exited 0. A `validation.severity` entry
|
|
287
|
+
* keyed `CUSTOM:<name>` for a check that is not declared is the mirror image: it
|
|
288
|
+
* parses (the schema validates the KEY's shape and cannot see
|
|
289
|
+
* `resources.checks`), applies to no finding, and says nothing. An adopter
|
|
290
|
+
* renames a check and leaves the override behind, or mistypes it while standing
|
|
291
|
+
* down an inherited one — and in the second direction the check they meant to
|
|
292
|
+
* silence keeps failing their build with no clue why.
|
|
293
|
+
*
|
|
294
|
+
* ⚠️ **A warning, not a refusal, and the asymmetry with `--check` is
|
|
295
|
+
* deliberate.** `--check` is a flag typed for THIS run, so a mistake is an
|
|
296
|
+
* operator error and exiting 2 costs nothing. A `severity` entry lives in a
|
|
297
|
+
* committed config that may legitimately be shared across repositories or
|
|
298
|
+
* outlive a check through a rename in flight; refusing it would be a new
|
|
299
|
+
* breaking config error, which is exactly the change this release already
|
|
300
|
+
* decided not to make twice (see `ResourcesConfigSchema`). Stderr, so the
|
|
301
|
+
* document on stdout stays parseable — the same channel and the same reasoning
|
|
302
|
+
* as the "no checks are declared" warning in {@link checkCommand}.
|
|
303
|
+
*
|
|
304
|
+
* 📌 The registry half of the key space needs no equivalent: a misspelled
|
|
305
|
+
* REGISTRY code is already refused by `SeverityOverrideCodeSchema`'s enum
|
|
306
|
+
* branch. Only the open `CUSTOM:` namespace can name something that does not
|
|
307
|
+
* exist.
|
|
308
|
+
*
|
|
309
|
+
* @param checks - The project's `resources.checks`
|
|
310
|
+
* @param validation - The project's `resources.validation`, or undefined
|
|
311
|
+
* @param logger - Where the warning goes (stderr)
|
|
312
|
+
*/
|
|
313
|
+
export declare function warnUndeclaredOverrides(checks: Readonly<Record<string, ResourceCheck>>, validation: SeverityOverrides | undefined, logger: Logger): void;
|
|
314
|
+
/**
|
|
315
|
+
* How a supervised run stopped short of publishing its own document.
|
|
316
|
+
*
|
|
317
|
+
* Two endings, and telling them apart is the whole reason this is a type rather
|
|
318
|
+
* than a number. A watchdog kill means *no progress within the budget*, and the
|
|
319
|
+
* remedy may genuinely be a larger bound. An abnormal death means *the run
|
|
320
|
+
* died* — most often out of memory — and there the budget was never involved,
|
|
321
|
+
* so advice to raise it is a false diagnosis that makes the situation worse.
|
|
322
|
+
*/
|
|
323
|
+
export type CheckRunEnding = {
|
|
324
|
+
readonly kind: 'budget';
|
|
325
|
+
readonly budgetSecs: number;
|
|
326
|
+
} | {
|
|
327
|
+
readonly kind: 'abnormal';
|
|
328
|
+
readonly death: AbnormalDeath;
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* The exit code Node uses for its own fatal abort, on EVERY platform.
|
|
332
|
+
*
|
|
333
|
+
* 🚨 **This is measured, and it is NOT the local platform's signal number.** On
|
|
334
|
+
* macOS and Linux 134 is the shell encoding `128 + SIGABRT`, where `SIGABRT` is
|
|
335
|
+
* 6. On Windows `os.constants.signals.SIGABRT` is **22** — MSVC numbers it
|
|
336
|
+
* differently — so deriving the code from that table gives 150 and matches
|
|
337
|
+
* nothing Node ever emits. A `windows-latest` run of the heap-abort case
|
|
338
|
+
* reported exactly **134**, the same as Unix: the number comes from Node's own
|
|
339
|
+
* abort path, not from the platform's signal table.
|
|
340
|
+
*
|
|
341
|
+
* 🪤 An earlier version of this file DID derive it from `os.constants.signals`,
|
|
342
|
+
* and its unit test derived the same way — so the test agreed with the code, the
|
|
343
|
+
* round-trip passed on every machine, and the pair was wrong together on the one
|
|
344
|
+
* platform the branch exists for. The value is therefore pinned as a measured
|
|
345
|
+
* fact, and a test asserts the number itself rather than re-deriving it.
|
|
346
|
+
*
|
|
347
|
+
* ⛔ Not a version constant: it decides nothing about whether stored data is
|
|
348
|
+
* still valid. It is an external protocol value, like an API header.
|
|
349
|
+
*/
|
|
350
|
+
export declare const NODE_FATAL_ABORT_EXIT_CODE = 134;
|
|
351
|
+
/**
|
|
352
|
+
* Rebuild the document from what an INTERRUPTED run left on disk.
|
|
353
|
+
*
|
|
354
|
+
* Both interruptions come here — the watchdog's kill and an abnormal death —
|
|
355
|
+
* because everything below this line is identical for them: the same recovered
|
|
356
|
+
* costs, the same non-overridable finding, the same refusal when there is no
|
|
357
|
+
* population. Only the sentences differ, and {@link CheckRunEnding} carries that.
|
|
358
|
+
*
|
|
359
|
+
* 🔑 It feeds {@link buildCheckOutputData}, the SAME builder a completed run
|
|
360
|
+
* uses. A second payload builder for this lane would be a second shape to
|
|
361
|
+
* keep in step with every future field — and the failure mode is silent, because
|
|
362
|
+
* nobody reads an interrupted run's document until the day they need it.
|
|
363
|
+
*
|
|
364
|
+
* 🚨 **A run interrupted during POPULATION gets no document at all.** There is no
|
|
365
|
+
* projection, so `population`, `populationSecs` and `membersEnumerated` have no
|
|
366
|
+
* honest value — and inventing `membersEnumerated: 0` would be worse than a
|
|
367
|
+
* blank, because that value already MEANS "this gate ran over an empty corpus",
|
|
368
|
+
* which is a different and wrong claim. The throw becomes an operator error
|
|
369
|
+
* (exit 2) through the same `handleCommandError` path everything else here uses.
|
|
370
|
+
*
|
|
371
|
+
* @param options - The wreckage
|
|
372
|
+
* @param options.entries - What `parseProgressLog` recovered
|
|
373
|
+
* @param options.root - The corpus root the parent resolved
|
|
374
|
+
* @param options.ending - Which way the run was interrupted
|
|
375
|
+
* @param options.durationMs - Wall time from spawn to ending
|
|
376
|
+
* @returns The input to {@link buildCheckOutputData}
|
|
377
|
+
* @throws When the child never reported a completed population
|
|
378
|
+
*/
|
|
379
|
+
export declare function buildInterruptedCheckInput(options: {
|
|
380
|
+
entries: readonly ProgressEntry[];
|
|
381
|
+
root: string;
|
|
382
|
+
ending: CheckRunEnding;
|
|
383
|
+
durationMs: number;
|
|
384
|
+
}): CheckPayloadInput;
|
|
385
|
+
/**
|
|
386
|
+
* Run the declared checks and resolve their severities — the whole of this
|
|
387
|
+
* verb's logic, with the database taken out.
|
|
388
|
+
*
|
|
389
|
+
* Exported and pure so the loop is provable without a spawn. It was not: every
|
|
390
|
+
* spawned case declared ONE check (the `--check` case declares two and filters
|
|
391
|
+
* to one, which the loop cannot distinguish), so `checksRun` was never observed
|
|
392
|
+
* above 1 and a `break` at the end of the loop would have left the suite green.
|
|
393
|
+
*
|
|
394
|
+
* Pure in the same sense the payload builder is, with ONE seam: it reads a
|
|
395
|
+
* clock. That is why the clock is a parameter — the measurement is the point of
|
|
396
|
+
* the `costs` it returns, and a duration nothing can pin is a number nobody can
|
|
397
|
+
* trust.
|
|
398
|
+
*
|
|
399
|
+
* @param options - The run
|
|
400
|
+
* @param options.checks - The declared checks
|
|
401
|
+
* @param options.only - A single check key, or undefined for all
|
|
402
|
+
* @param options.ask - Runs one statement against the populated projection
|
|
403
|
+
* @param options.validation - The project's severity overrides, or undefined
|
|
404
|
+
* @param options.membersEnumerated - How many members the population enumerated.
|
|
405
|
+
* Told rather than asked, because no answer can reveal it: an `ask` over an
|
|
406
|
+
* empty projection and an `ask` over a clean one both return no rows
|
|
407
|
+
* @param options.now - The measurement clock in milliseconds, defaulting to
|
|
408
|
+
* `performance.now()`. Injected only so a unit test can pin an exact per-check
|
|
409
|
+
* duration; nothing in production passes it
|
|
410
|
+
* @param options.onProgress - Where each check's `start` and cost are announced
|
|
411
|
+
* so an outside supervisor can see them, or undefined when the run is not
|
|
412
|
+
* supervised. Optional rather than required because `--budget 0` and every
|
|
413
|
+
* unit case run with nobody watching
|
|
414
|
+
* @returns The resolved findings, and one cost record per check that ran
|
|
415
|
+
*/
|
|
416
|
+
export declare function runDeclaredChecks(options: {
|
|
417
|
+
checks: Readonly<Record<string, ResourceCheck>>;
|
|
418
|
+
only: string | undefined;
|
|
419
|
+
ask: AskProjection;
|
|
420
|
+
validation: SeverityOverrides | undefined;
|
|
421
|
+
membersEnumerated: number;
|
|
422
|
+
now?: () => number;
|
|
423
|
+
onProgress?: ProgressSink | undefined;
|
|
424
|
+
}): {
|
|
425
|
+
issues: ValidationIssue[];
|
|
426
|
+
costs: CheckCost[];
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* Run the project's declared checks against its projection.
|
|
430
|
+
*
|
|
431
|
+
* ## 🚨 Why this verb spawns a child and `vat resources query` does not
|
|
432
|
+
*
|
|
433
|
+
* Both verbs run SQL an adopter wrote, over the same projection, through the
|
|
434
|
+
* same `withQueriedProjection` — which does NOT diverge here, and must not. The
|
|
435
|
+
* fork is this function and nothing below it.
|
|
436
|
+
*
|
|
437
|
+
* `query`'s author is at the keyboard, and Ctrl-C already works for them. It
|
|
438
|
+
* works for one reason worth stating, because it is fragile: NO signal handler
|
|
439
|
+
* is installed anywhere on this path. A process blocked in synchronous
|
|
440
|
+
* `node:sqlite` dies instantly on SIGINT while that remains true, and SURVIVES
|
|
441
|
+
* SIGINT and SIGTERM the moment a handler exists — the handler is a JS callback
|
|
442
|
+
* and the event loop that would schedule it is the blocked resource. Adding one
|
|
443
|
+
* would take Ctrl-C away from `query` without adding anything to `check`.
|
|
444
|
+
*
|
|
445
|
+
* `check` runs unattended in CI, where nobody is there to press it. So it gets a
|
|
446
|
+
* bound enforced from outside itself, and a hang becomes a bounded failure
|
|
447
|
+
* instead of a job that burns its runner minutes and reports nothing.
|
|
448
|
+
*
|
|
449
|
+
* @param pathArg - The corpus root, or omitted for the current directory
|
|
450
|
+
* @param options - Parsed command-line options
|
|
451
|
+
*/
|
|
452
|
+
export declare function checkCommand(pathArg: string | undefined, options: CheckOptions): Promise<void>;
|
|
453
|
+
export {};
|
|
454
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/commands/resources/check.ts"],"names":[],"mappings":"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"}
|