bareloop 0.8.0 → 0.9.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/CHANGELOG.md +421 -0
- package/README.md +10 -3
- package/bareloop.context.md +198 -17
- package/package.json +1 -1
- package/src/authorflow.js +1280 -0
- package/src/authoring.js +1296 -0
- package/src/authorjob.js +793 -0
- package/src/authorscout.js +706 -0
- package/src/bridges.js +2 -2
- package/src/declaredclose.js +519 -0
- package/src/index.js +72 -0
- package/src/job.js +48 -4
- package/src/kinds.js +1354 -0
- package/src/ledger.js +13 -0
- package/src/plan.js +26 -1
- package/src/planrun.js +239 -16
- package/src/ralph.js +19 -4
- package/src/reuse.js +68 -7
- package/src/root.js +8 -1
- package/src/run.js +10 -3
- package/src/text.js +120 -0
- package/src/workbranch.js +261 -0
- package/types/authorflow.d.ts +720 -0
- package/types/authoring.d.ts +447 -0
- package/types/authorjob.d.ts +241 -0
- package/types/authorscout.d.ts +307 -0
- package/types/declaredclose.d.ts +174 -0
- package/types/index.d.ts +9 -1
- package/types/job.d.ts +1 -0
- package/types/kinds.d.ts +343 -0
- package/types/plan.d.ts +18 -0
- package/types/planrun.d.ts +10 -3
- package/types/ralph.d.ts +1 -0
- package/types/run.d.ts +10 -2
- package/types/text.d.ts +84 -0
- package/types/workbranch.d.ts +102 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE CEILING (hamr, 2026-08-08, *"yes to both, go"*): the picked class is a
|
|
3
|
+
* PROMISE, and this is what the composition actually demands.
|
|
4
|
+
*
|
|
5
|
+
* Every kind carries the class of verdict it can honestly render, so a
|
|
6
|
+
* declaration's ceiling is the HIGHEST class any of its stages needs. A pick
|
|
7
|
+
* below that ceiling is a silent UPGRADE — a judgment ruler running under a
|
|
8
|
+
* green promise, which is exactly the fake-hard verdict `CLASS_BY_CLOSE` and
|
|
9
|
+
* `CLASS_BY_VERDICT` exist to stop, defeated from ABOVE by never letting the
|
|
10
|
+
* illegal pair be formed.
|
|
11
|
+
*
|
|
12
|
+
* INERT IN v1 BY CONSTRUCTION, which is why it is cheap now: every LIVE kind is
|
|
13
|
+
* mechanical, so no declaration a v1 catalogue can express reaches above green.
|
|
14
|
+
* It is written before the second class exists so the first soft-green kind is
|
|
15
|
+
* not the thing that discovers the question.
|
|
16
|
+
*
|
|
17
|
+
* A kind the catalogue does not know contributes NOTHING — it already carries an
|
|
18
|
+
* `unknown-kind` red, and guessing a class for it would be deriving the promise
|
|
19
|
+
* from a typo. A catalogue entry with no class at all THROWS: the catalogue is
|
|
20
|
+
* OURS, and failing loudly beats weighing a kind whose honesty nobody stated.
|
|
21
|
+
* @param {any} declaration
|
|
22
|
+
* @param {Record<string, KindSpec>} [catalogue]
|
|
23
|
+
* @returns {{class: string, kind: string, stage: string|null, locked: boolean}|null}
|
|
24
|
+
*/
|
|
25
|
+
export function closeCeiling(declaration: any, catalogue?: Record<string, KindSpec>): {
|
|
26
|
+
class: string;
|
|
27
|
+
kind: string;
|
|
28
|
+
stage: string | null;
|
|
29
|
+
locked: boolean;
|
|
30
|
+
} | null;
|
|
31
|
+
/**
|
|
32
|
+
* Which kinds can carry an environment at all, read off the CATALOGUE rather
|
|
33
|
+
* than a hand-kept list. ONE spelling, because two consumers must agree
|
|
34
|
+
* EXACTLY: `applyGenreEnv` injects the genre's variable into these stages and
|
|
35
|
+
* nowhere else, and the validator's completeness rule demands it on these
|
|
36
|
+
* stages and nowhere else. A second copy that drifted either way is a hole —
|
|
37
|
+
* stages injected but unchecked, or stages checked for what nothing injects.
|
|
38
|
+
* @param {string} kind @param {Record<string, KindSpec>} [catalogue]
|
|
39
|
+
*/
|
|
40
|
+
export function envCapableKind(kind: string, catalogue?: Record<string, KindSpec>): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* The floor's decision for one declared `cmd`, as a reason or null.
|
|
43
|
+
*
|
|
44
|
+
* NORMALISATION FIRST, because that is where the dodge lives: `/usr/bin/rm`
|
|
45
|
+
* carries the same program as `rm` and only a basename read taken AFTER
|
|
46
|
+
* splitting the path can see it. Case is folded for the same reason.
|
|
47
|
+
*
|
|
48
|
+
* A cmd naming a program OUTSIDE the repository — an absolute path, or one that
|
|
49
|
+
* climbs out with `..` — is refused whatever its basename says. Two reasons, and
|
|
50
|
+
* both are the fail-safe direction: the validator has no repository in hand at
|
|
51
|
+
* every call site (the job validator judges a signed spec with no tree), so
|
|
52
|
+
* "outside" cannot be decided per-machine; and a machine-absolute path inside a
|
|
53
|
+
* SIGNED artefact grades a different machine than the one it was signed on.
|
|
54
|
+
* @param {string} cmd @returns {string|null}
|
|
55
|
+
*/
|
|
56
|
+
export function deniedCommandReason(cmd: string): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* The picked class's mandatory guards, FULLY ENUMERATED (D13 forward-compat
|
|
59
|
+
* point 3: an omittable-with-a-default field is the omitted-`tools` shape, where
|
|
60
|
+
* widening changes what runs without changing what was signed — so the guards
|
|
61
|
+
* are stored spelled out, and the hash is taken over the resolved form).
|
|
62
|
+
*
|
|
63
|
+
* `fill` names the ONLY slot the model supplies. `changed-from-seed`'s
|
|
64
|
+
* allowPrefixes is the job's own target scope and cannot be ours; everything
|
|
65
|
+
* else — including `no-suppressions`' absent scope — is.
|
|
66
|
+
*
|
|
67
|
+
* AN EMPTY BATTERY IS IMPOSSIBLE for a known class and a known language, and
|
|
68
|
+
* that is enforced rather than asserted: an unknown class, a locked class, an
|
|
69
|
+
* unknown language, a battery that resolved to nothing, and a composed param
|
|
70
|
+
* that resolved to nothing all THROW. F59's shape at the load-bearing decision
|
|
71
|
+
* of the design — a suppression scan with no patterns reads clean exactly like
|
|
72
|
+
* one that scanned correctly, and it lands in a SIGNED artefact.
|
|
73
|
+
*
|
|
74
|
+
* Returns a fresh deep copy each call: a frozen constant handed to a caller that
|
|
75
|
+
* edits it is one shared battery away from a silently weakened guard.
|
|
76
|
+
* @param {{verdictType: string, lang: string}} o
|
|
77
|
+
* @returns {{name: string, kind: string, params: Record<string, any>, compose: string[], fill: string[]}[]}
|
|
78
|
+
*/
|
|
79
|
+
export function classGuards({ verdictType, lang }: {
|
|
80
|
+
verdictType: string;
|
|
81
|
+
lang: string;
|
|
82
|
+
}): {
|
|
83
|
+
name: string;
|
|
84
|
+
kind: string;
|
|
85
|
+
params: Record<string, any>;
|
|
86
|
+
compose: string[];
|
|
87
|
+
fill: string[];
|
|
88
|
+
}[];
|
|
89
|
+
/**
|
|
90
|
+
* The genre's environment for this patient — ours to inject at execution (M3),
|
|
91
|
+
* never model-authored. An entry with no value produces NO VARIABLE: an empty
|
|
92
|
+
* `MYPYPATH` is not the same instruction as an unset one, and shipping `''`
|
|
93
|
+
* would silently change how mypy resolves.
|
|
94
|
+
* @param {string} lang
|
|
95
|
+
* @param {{sourcePrefixes?: string[]}} [o]
|
|
96
|
+
* @returns {Record<string, string>}
|
|
97
|
+
*/
|
|
98
|
+
export function genreEnv(lang: string, { sourcePrefixes }?: {
|
|
99
|
+
sourcePrefixes?: string[];
|
|
100
|
+
}): Record<string, string>;
|
|
101
|
+
/** The names the genre OWNS — the validator refuses a declaration that authors
|
|
102
|
+
* one of them, because ownership is only real if it is mechanical.
|
|
103
|
+
* @param {string} lang @returns {string[]} */
|
|
104
|
+
export function genreOwnedEnvNames(lang: string): string[];
|
|
105
|
+
/**
|
|
106
|
+
* GROUNDING for a RECORDED genre environment — the provenance half of the
|
|
107
|
+
* owned-env rule, and the reason the by-value comparison is worth anything.
|
|
108
|
+
*
|
|
109
|
+
* The value check proves the envelope's `genreEnv` and the stage's `params.env`
|
|
110
|
+
* AGREE. Both copies live in the same hand-editable spec, so agreement is
|
|
111
|
+
* something a forger gets for free: a spec carrying
|
|
112
|
+
* `MYPYPATH=/tmp/attacker-stubs` in both places is perfectly self-consistent and
|
|
113
|
+
* would point the checker at a tree nobody signed. Agreement is not provenance.
|
|
114
|
+
*
|
|
115
|
+
* What a forger does NOT own is the repository at the seed. Every value the
|
|
116
|
+
* arbiter can build is `genreEnv`'s join of `sourcePrefixes`, and those prefixes
|
|
117
|
+
* were already filtered against the seed listing before the join — so each
|
|
118
|
+
* ELEMENT of a genuine value is a path the listing SELECTS, exactly like hamr's
|
|
119
|
+
* listing rule for a declared path. Grounding therefore accepts precisely what
|
|
120
|
+
* `applyGenreEnv` produces and refuses everything else, without needing a second
|
|
121
|
+
* spelling of what "ours" means.
|
|
122
|
+
*
|
|
123
|
+
* Element-wise, never whole-value: a joined list is as strong as its weakest
|
|
124
|
+
* element, and one real prefix must not launder the rest. A root spelling is
|
|
125
|
+
* ungrounded here rather than waved through the way `checkPaths` waves it —
|
|
126
|
+
* `genreEnv` filters those out before joining, so the arbiter can never produce
|
|
127
|
+
* one, and a validator that admits what its own producer cannot emit is a gap.
|
|
128
|
+
*
|
|
129
|
+
* Callers that hold a listing only; the deferred job-spec gate cannot run this
|
|
130
|
+
* and does not pretend to (see `validateCloseDecl`).
|
|
131
|
+
* @param {string} lang
|
|
132
|
+
* @param {Record<string, string>} recorded what the envelope claims the arbiter injected
|
|
133
|
+
* @param {string[]} listing repo-relative paths at the seed
|
|
134
|
+
* @returns {{name: string, value: string, element: string, resolved: string}[]} one row per ungrounded element
|
|
135
|
+
*/
|
|
136
|
+
export function ungroundedGenreEnv(lang: string, recorded: Record<string, string>, listing: string[]): {
|
|
137
|
+
name: string;
|
|
138
|
+
value: string;
|
|
139
|
+
element: string;
|
|
140
|
+
resolved: string;
|
|
141
|
+
}[];
|
|
142
|
+
/**
|
|
143
|
+
* Validate an authored close DECLARATION. Never throws on model output — every
|
|
144
|
+
* failure is a named red, in the shipped `{ok, reds, <parsed>}` shape, and the
|
|
145
|
+
* parsed value is the RESOLVED declaration (every short-form parser expanded),
|
|
146
|
+
* because that is the form the executor runs and the signature covers.
|
|
147
|
+
*
|
|
148
|
+
* `listing`, `guards` and `envOwned` are REQUIRED, and their absence is a red
|
|
149
|
+
* rather than a skipped check — all three guard the SAME failure: a validator
|
|
150
|
+
* that silently stops checking when handed nothing to check against reports a
|
|
151
|
+
* clean declaration it never examined. v1 only admits a job with a runnable
|
|
152
|
+
* patient and a git seed (D13), so the listing always exists, and D5's guards
|
|
153
|
+
* exist by construction. `envOwned` is separated into absent-vs-empty for
|
|
154
|
+
* F59's reason exactly: `[]` is a genre that owns no variables (JS), and
|
|
155
|
+
* `undefined` is a caller that never asked — the two must not read alike.
|
|
156
|
+
*
|
|
157
|
+
* The CATALOGUE is ours, not model input: a malformed one is a bareloop bug and
|
|
158
|
+
* is allowed to throw, because failing loudly beats a validator that quietly
|
|
159
|
+
* stops enforcing a rule it was configured out of.
|
|
160
|
+
*
|
|
161
|
+
* `deferListing: true` is the ONE way to run without a listing, and it must be
|
|
162
|
+
* spelled literally. It exists for exactly one caller — the job-spec validator,
|
|
163
|
+
* which judges a signed `closeDecl` with no repository in hand — and it does NOT
|
|
164
|
+
* make the listing optional: it moves that half of the gate to the runner, which
|
|
165
|
+
* re-validates GROUNDED against the real seed before any stage runs. Two checks
|
|
166
|
+
* ride on the listing and both are named here rather than discovered later: the
|
|
167
|
+
* path rule (a path SELECTS or it does not exist), and the SCOPED-job derivation
|
|
168
|
+
* that arms the F84 one-population law. With the listing deferred, neither
|
|
169
|
+
* fires, and `grounded: false` on the result is how a caller knows.
|
|
170
|
+
*
|
|
171
|
+
* `verdictType` is REQUIRED for the same reason: it is the PROMISE the ceiling
|
|
172
|
+
* rule checks the composition against, and a validator with no pick in hand
|
|
173
|
+
* cannot check it. Absent or unknown is `class-absent`, naming the closed set.
|
|
174
|
+
*
|
|
175
|
+
* @param {any} declaration the parsed model output
|
|
176
|
+
* @param {{catalogue?: Record<string, KindSpec>, listing?: string[]|null,
|
|
177
|
+
* guards?: {name: string, kind: string, params: Record<string, any>, fill: string[]}[]|null,
|
|
178
|
+
* envOwned?: string[]|null, envInjected?: Record<string, string>|null, deferListing?: boolean,
|
|
179
|
+
* verdictType?: string|null}} [opts]
|
|
180
|
+
* `listing` — repo-relative paths at the seed (`git ls-tree -r --name-only`).
|
|
181
|
+
* `guards` — the picked class's injected guards (`classGuards`).
|
|
182
|
+
* `verdictType` — the class the USER picked (`VERDICT_CLASSES`).
|
|
183
|
+
* `envOwned` — env names the genre injects (`genreOwnedEnvNames`), `[]` when it owns none.
|
|
184
|
+
* `envInjected` — the env the ARBITER itself injected (`genreEnv`'s output), for a
|
|
185
|
+
* POST-injection re-validation. Omitted is the PRE-injection form: every owned name
|
|
186
|
+
* is the model's and reds. Supplied, an owned name is accepted only when its value is
|
|
187
|
+
* EXACTLY the injected one — a wrong value is the model's guess or corruption.
|
|
188
|
+
* `deferListing` — literally `true` to run the tree-independent half only.
|
|
189
|
+
* @returns {{ok: boolean, reds: Red[], declaration: any, grounded: boolean,
|
|
190
|
+
* scoped: {scoped: boolean, via: string|null},
|
|
191
|
+
* ceiling: {class: string, kind: string, stage: string|null, locked: boolean}|null}}
|
|
192
|
+
*/
|
|
193
|
+
export function validateDeclaration(declaration: any, opts?: {
|
|
194
|
+
catalogue?: Record<string, KindSpec>;
|
|
195
|
+
listing?: string[] | null;
|
|
196
|
+
guards?: {
|
|
197
|
+
name: string;
|
|
198
|
+
kind: string;
|
|
199
|
+
params: Record<string, any>;
|
|
200
|
+
fill: string[];
|
|
201
|
+
}[] | null;
|
|
202
|
+
envOwned?: string[] | null;
|
|
203
|
+
envInjected?: Record<string, string> | null;
|
|
204
|
+
deferListing?: boolean;
|
|
205
|
+
verdictType?: string | null;
|
|
206
|
+
}): {
|
|
207
|
+
ok: boolean;
|
|
208
|
+
reds: Red[];
|
|
209
|
+
declaration: any;
|
|
210
|
+
grounded: boolean;
|
|
211
|
+
scoped: {
|
|
212
|
+
scoped: boolean;
|
|
213
|
+
via: string | null;
|
|
214
|
+
};
|
|
215
|
+
ceiling: {
|
|
216
|
+
class: string;
|
|
217
|
+
kind: string;
|
|
218
|
+
stage: string | null;
|
|
219
|
+
locked: boolean;
|
|
220
|
+
} | null;
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* The declaration the EXECUTOR sees and the SIGNATURE covers: every
|
|
224
|
+
* `count-not-worse` parser resolved to `{terms: [...]}`, so the short form stops
|
|
225
|
+
* existing at this boundary and there is exactly one shape downstream (D13
|
|
226
|
+
* forward-compat point 3 — the hash is taken over the RESOLVED form, or an
|
|
227
|
+
* omittable-with-a-default field changes what runs without changing what was
|
|
228
|
+
* signed).
|
|
229
|
+
*
|
|
230
|
+
* A parser that would not normalise is left VERBATIM: it already carries a red,
|
|
231
|
+
* and rewriting it would hide what the model actually wrote.
|
|
232
|
+
* @param {any} declaration
|
|
233
|
+
*/
|
|
234
|
+
export function normalizeDeclaration(declaration: any): any;
|
|
235
|
+
/** @typedef {{code: string, path: string, detail: string, [k: string]: any}} Red */
|
|
236
|
+
/** @typedef {{required: readonly string[], optional: readonly string[], pathParams: readonly string[], locked?: true, verdictClass: string, shape: string, asserts: string}} KindSpec */
|
|
237
|
+
/** the whole menu, in ascending order of what it takes to render the verdict */
|
|
238
|
+
export const VERDICT_CLASSES: readonly string[];
|
|
239
|
+
/** declared-but-locked: selecting one is COUNTED demand, never an admission */
|
|
240
|
+
export const LOCKED_CLASSES: readonly string[];
|
|
241
|
+
/** the classes v1 actually builds — exactly one */
|
|
242
|
+
export const LIVE_CLASSES: readonly string[];
|
|
243
|
+
/**
|
|
244
|
+
* The whole vocabulary, as DATA. `shape` and `asserts` are the strings the
|
|
245
|
+
* authoring prompt renders (M3) — the prompt and this validator must judge the
|
|
246
|
+
* same facts, so they read one catalogue rather than two (the drift class
|
|
247
|
+
* SECRET_PATTERNS exists to prevent, one layer up).
|
|
248
|
+
*
|
|
249
|
+
* `pathParams` names every param that carries a repository path, in dotted
|
|
250
|
+
* form. It is data rather than a switch so hamr's listing rule reaches a new
|
|
251
|
+
* path-bearing param the day one is added, instead of the day someone
|
|
252
|
+
* remembers to widen a condition.
|
|
253
|
+
*
|
|
254
|
+
* `verdictClass` is the class of verdict this kind can HONESTLY render, and it
|
|
255
|
+
* is what makes the user's pick a promise the composer must keep (PRD v1.57 §1).
|
|
256
|
+
* Every live kind is `green` — a command's measurement is the truth — so the
|
|
257
|
+
* ceiling rule is inert in v1 by construction; the two locked kinds carry the
|
|
258
|
+
* classes they belong to so the rule is already correct the day one goes live.
|
|
259
|
+
*
|
|
260
|
+
* Optionality is read off the prereg §5 table, with ONE deliberate divergence
|
|
261
|
+
* from the gate-2 POC validator, named because it reverses a POC behaviour:
|
|
262
|
+
* `pattern-absent-in-diff.scope` is OPTIONAL here and the guard ships without
|
|
263
|
+
* it. Under addendum 6 the guard's scope is GENRE property and the answer is
|
|
264
|
+
* "every changed file of these extensions" — an absent scope is exactly that
|
|
265
|
+
* (M1's `inScope` admits everything when no scope object is present). The POC
|
|
266
|
+
* required it, and required it filled, which is how round 3's arm A came to
|
|
267
|
+
* narrow the scan and call it stricter.
|
|
268
|
+
* @type {Record<string, KindSpec>}
|
|
269
|
+
*/
|
|
270
|
+
export const KIND_CATALOGUE: Record<string, KindSpec>;
|
|
271
|
+
export const CATALOGUE_KINDS: readonly string[];
|
|
272
|
+
export const LOCKED_KINDS: readonly string[];
|
|
273
|
+
/** the catalogue's live half — asserted EQUAL to the executor's own LIVE_KINDS
|
|
274
|
+
* by the suite, both directions: a kind the catalogue offers and the executor
|
|
275
|
+
* cannot run is a close that stops at runtime, and a kind the executor runs
|
|
276
|
+
* that the catalogue never names is a capability nothing can reach. */
|
|
277
|
+
export const CATALOGUE_LIVE_KINDS: readonly string[];
|
|
278
|
+
export const DIRECTIONS: readonly string[];
|
|
279
|
+
/** D12: the close stores the COUNTING RULE, never the number. "seed" is measured
|
|
280
|
+
* at this run's own seed every run; 0 is literally zero. A frozen constant (the
|
|
281
|
+
* hand-written closes' `SEED_ERRORS 63`) is exactly what this menu retires. */
|
|
282
|
+
export const BASELINES: readonly (string | number)[];
|
|
283
|
+
/** a runaway stage list is a red, not a bill — the sibling of M1's MAX_TERMS */
|
|
284
|
+
export const MAX_STAGES: 12;
|
|
285
|
+
/**
|
|
286
|
+
* THE DENY FLOOR under a declared command (hamr's ruling, PRD v1.57 §3: *"there
|
|
287
|
+
* should be a floor of all dangerous things… straight out block… no one wants
|
|
288
|
+
* `rm -rf` allowed either ways"*).
|
|
289
|
+
*
|
|
290
|
+
* Four families, and each one is here for a different reason:
|
|
291
|
+
* - SHELL INTERPRETERS. A shell runs anything, so admitting one makes every
|
|
292
|
+
* other entry decoration — the D3 line ("the danger is in the ACTIONS, not
|
|
293
|
+
* the SYNTAX") reappearing at the close's own spawn.
|
|
294
|
+
* - DESTRUCTIVE / SYSTEM commands. The `rm -rf` class the ruling names, plus
|
|
295
|
+
* the machine-level siblings (`dd`, the `mkfs` FAMILY, shutdown/reboot) and
|
|
296
|
+
* privilege escalation.
|
|
297
|
+
* - FETCH-AND-RUN vectors (`curl`, `wget`). A close that downloads its own
|
|
298
|
+
* instrument is a close nobody signed.
|
|
299
|
+
* - INDIRECTION (`env`, `eval`, `exec`, `xargs`). They run a program the
|
|
300
|
+
* declaration never names, which defeats every entry above by construction.
|
|
301
|
+
*
|
|
302
|
+
* It is a FLOOR, and MONOTONIC: names are only ever ADDED, never removed or
|
|
303
|
+
* narrowed (the F49 precedent — closing a false negative is the allowed
|
|
304
|
+
* direction; chasing a false positive is not). A legitimate runner refused here
|
|
305
|
+
* is fixed by declaring the runner, never by shrinking the floor.
|
|
306
|
+
*
|
|
307
|
+
* It is NOT A SANDBOX, and nothing here claims to be one. The local-trust model
|
|
308
|
+
* of v1.41 stands intact and its limitations are written out in PRD v1.57 §3:
|
|
309
|
+
* close children keep the operator's OS user, network egress and file access;
|
|
310
|
+
* `args` are not inspected (`node -e <anything>` is reachable and always was);
|
|
311
|
+
* resource use is bounded by liveness checks, not quotas. The floor narrows
|
|
312
|
+
* blast radius; it does not promise containment.
|
|
313
|
+
*/
|
|
314
|
+
export const DENIED_COMMANDS: readonly string[];
|
|
315
|
+
/**
|
|
316
|
+
* THE FROZEN TYPES GENRE TEMPLATE — prereg addendum 3's six policy points,
|
|
317
|
+
* VERBATIM. The suite reads the prereg and compares BYTES, so a paraphrase here
|
|
318
|
+
* fails the build rather than quietly changing what every future close is
|
|
319
|
+
* authored against. It deliberately carries no repo-specific command, path, env
|
|
320
|
+
* value or regex: round 2 measured that stating the LAW still leaves the model
|
|
321
|
+
* to find the VALUE, and that is the axis the build must keep live.
|
|
322
|
+
*/
|
|
323
|
+
export const TYPES_GENRE_TEMPLATE: "1. The graded instrument is the STRICT form of the language's type checker, regardless of what\n the repo's own scripts run. If the repo's script omits strictness, the close adds it.\n2. Tools are invoked so their binaries actually resolve \u2014 through the project's own package\n runner or language module runner, never a bare binary name.\n3. The stage skeleton, in first-red-wins order: changed-from-seed (guard) \u2192 typecheck (error\n count IN the target scope, baseline 0, lower-is-better) \u2192 typecheck-outside (error count\n OUTSIDE the target scope, baseline measured at seed, a ceiling \u2014 required whenever the job\n scopes to a subset of the tree; omitted only for whole-tree jobs) \u2192 tests-kept (a floor on\n tests that actually EXECUTED, baseline at seed, higher-is-better; a skipped or deselected\n test did not run and must not count) \u2192 suite-green (the suite exits clean AND reports zero\n failing tests \u2014 two assertions) \u2192 no-suppressions (guard).\n4. One population per stage \u2014 two structurally different counts never share a stage.\n5. The checker must judge the PATIENT's own tree: if imports could resolve to an installed or\n editable copy elsewhere, the environment is set so they resolve inside the patient.\n6. A number the tool did not report is unknown, never zero.";
|
|
324
|
+
export const GENRE_LANGUAGES: readonly string[];
|
|
325
|
+
/**
|
|
326
|
+
* THE GENRE, as data. The suppression batteries are the hand-written closes'
|
|
327
|
+
* own `SUPPRESSIONS` tables (`scripts/u-pulselog-close.mjs:35`,
|
|
328
|
+
* `scripts/u-spawner-close.mjs:34`) — operator-owned genre knowledge, minted by
|
|
329
|
+
* paying for live runs. `unknown` is deliberately NOT a JS suppression and not
|
|
330
|
+
* a Python one: it forces narrowing at the use site, which is real typing work.
|
|
331
|
+
*
|
|
332
|
+
* `env` is the addendum-6 residue expressed as data. Python's `MYPYPATH` is
|
|
333
|
+
* load-bearing and was found by probe, never by reading: the aurora patient sets
|
|
334
|
+
* `explicit_package_bases`, so without it a sibling import falls through to an
|
|
335
|
+
* editable install pointing at a DIFFERENT checkout and a cross-module fix is
|
|
336
|
+
* graded against unedited source. It moves no seed number, which is why no
|
|
337
|
+
* seed-verdict read can ever catch its absence — the only place it can live is
|
|
338
|
+
* here, in genre data, injected by the flow.
|
|
339
|
+
*/
|
|
340
|
+
export const TYPES_GENRE: Readonly<{
|
|
341
|
+
name: "TYPES";
|
|
342
|
+
template: "1. The graded instrument is the STRICT form of the language's type checker, regardless of what\n the repo's own scripts run. If the repo's script omits strictness, the close adds it.\n2. Tools are invoked so their binaries actually resolve — through the project's own package\n runner or language module runner, never a bare binary name.\n3. The stage skeleton, in first-red-wins order: changed-from-seed (guard) → typecheck (error\n count IN the target scope, baseline 0, lower-is-better) → typecheck-outside (error count\n OUTSIDE the target scope, baseline measured at seed, a ceiling — required whenever the job\n scopes to a subset of the tree; omitted only for whole-tree jobs) → tests-kept (a floor on\n tests that actually EXECUTED, baseline at seed, higher-is-better; a skipped or deselected\n test did not run and must not count) → suite-green (the suite exits clean AND reports zero\n failing tests — two assertions) → no-suppressions (guard).\n4. One population per stage — two structurally different counts never share a stage.\n5. The checker must judge the PATIENT's own tree: if imports could resolve to an installed or\n editable copy elsewhere, the environment is set so they resolve inside the patient.\n6. A number the tool did not report is unknown, never zero.";
|
|
343
|
+
languages: Readonly<{
|
|
344
|
+
js: Readonly<{
|
|
345
|
+
suppressions: readonly (Readonly<{
|
|
346
|
+
id: "ts-ignore";
|
|
347
|
+
regex: "@ts-ignore";
|
|
348
|
+
}> | Readonly<{
|
|
349
|
+
id: "ts-expect-error";
|
|
350
|
+
regex: "@ts-expect-error";
|
|
351
|
+
}> | Readonly<{
|
|
352
|
+
id: "ts-nocheck";
|
|
353
|
+
regex: "@ts-nocheck";
|
|
354
|
+
}> | Readonly<{
|
|
355
|
+
id: "eslint-disable";
|
|
356
|
+
regex: "eslint-disable";
|
|
357
|
+
}> | Readonly<{
|
|
358
|
+
id: "any";
|
|
359
|
+
regex: "(?:[{<|(\\[:,]|\\bas)\\s*any\\b|\\bany\\[\\]";
|
|
360
|
+
}> | Readonly<{
|
|
361
|
+
id: "any-star";
|
|
362
|
+
regex: "@\\w+\\s*\\{\\s*[*?]\\s*\\}";
|
|
363
|
+
}> | Readonly<{
|
|
364
|
+
id: "cast";
|
|
365
|
+
regex: "@type\\s*\\{.*\\}\\s*\\*\\/\\s*\\(";
|
|
366
|
+
}>)[];
|
|
367
|
+
extensions: readonly string[];
|
|
368
|
+
/** no import-resolution hazard on this runner — an EMPTY list, declared,
|
|
369
|
+
* never an absent field that would read as "not looked into" (F59) */
|
|
370
|
+
env: readonly never[];
|
|
371
|
+
}>;
|
|
372
|
+
python: Readonly<{
|
|
373
|
+
suppressions: readonly (Readonly<{
|
|
374
|
+
id: "ignore";
|
|
375
|
+
regex: "#\\s*type:\\s*ignore";
|
|
376
|
+
}> | Readonly<{
|
|
377
|
+
id: "any";
|
|
378
|
+
regex: "\\bAny\\b";
|
|
379
|
+
}> | Readonly<{
|
|
380
|
+
id: "cast";
|
|
381
|
+
regex: "\\bcast\\s*\\(";
|
|
382
|
+
}> | Readonly<{
|
|
383
|
+
id: "noqa";
|
|
384
|
+
regex: "#\\s*noqa";
|
|
385
|
+
}> | Readonly<{
|
|
386
|
+
id: "mypy-disable";
|
|
387
|
+
regex: "#\\s*mypy:\\s*disable";
|
|
388
|
+
}>)[];
|
|
389
|
+
extensions: readonly string[];
|
|
390
|
+
env: readonly Readonly<{
|
|
391
|
+
name: "MYPYPATH";
|
|
392
|
+
from: "sourcePrefixes";
|
|
393
|
+
join: ":";
|
|
394
|
+
why: string;
|
|
395
|
+
}>[];
|
|
396
|
+
}>;
|
|
397
|
+
}>;
|
|
398
|
+
}>;
|
|
399
|
+
/**
|
|
400
|
+
* THE GUARD BATTERY, KEYED BY VERDICT CLASS (hamr's ruling, PRD v1.57 §2).
|
|
401
|
+
*
|
|
402
|
+
* D5's battery was genre-keyed data. Under class-keyed interviews it has no
|
|
403
|
+
* genre to hang from, and the ruling gives it the same home the interview took:
|
|
404
|
+
* **the battery attaches to the verdict class the user picked** — not to a
|
|
405
|
+
* problem-genre label, and not per catalogue KIND.
|
|
406
|
+
*
|
|
407
|
+
* WHY THE CLASS. What a battery is FOR is the class of dishonesty the class of
|
|
408
|
+
* VERDICT admits. A green job is a job whose *done* is claimed to be
|
|
409
|
+
* machine-checkable, so it carries the green battery whatever problem it came
|
|
410
|
+
* from — that is the anti-suppression obligation the F87 genre earned, and it
|
|
411
|
+
* must not travel with a label the interview no longer asks for.
|
|
412
|
+
*
|
|
413
|
+
* ATTACHMENT POINT vs CONTENTS, and the split is the whole implementation:
|
|
414
|
+
* - the battery's STRUCTURE and its un-removability key off the CLASS. That
|
|
415
|
+
* is this table: which guards exist, what they assert, which slot is the
|
|
416
|
+
* model's (`fill`), and which params are ours.
|
|
417
|
+
* - the battery's CONTENTS fill in at COMPOSITION (`compose`), because a
|
|
418
|
+
* suppression pattern, a file extension and a checker's escape hatch belong
|
|
419
|
+
* to the TOOL the declaration names, and nothing before composition knows
|
|
420
|
+
* that tool. `classGuards` resolves them from the language data below.
|
|
421
|
+
*
|
|
422
|
+
* A LOCKED class carries `guards: null`, not `[]`. Absent is never empty (F59):
|
|
423
|
+
* `[]` would read as "this class needs no guards", which is exactly the sentence
|
|
424
|
+
* D5 exists to make unsayable. Nothing ever reaches it — admission refuses a
|
|
425
|
+
* locked class before its battery is asked for — and `classGuards` throws rather
|
|
426
|
+
* than hand back nothing if anything ever does.
|
|
427
|
+
* @type {Record<string, {locked: boolean, guards: readonly any[]|null}>}
|
|
428
|
+
*/
|
|
429
|
+
export const CLASS_BATTERIES: Record<string, {
|
|
430
|
+
locked: boolean;
|
|
431
|
+
guards: readonly any[] | null;
|
|
432
|
+
}>;
|
|
433
|
+
export type Red = {
|
|
434
|
+
code: string;
|
|
435
|
+
path: string;
|
|
436
|
+
detail: string;
|
|
437
|
+
[k: string]: any;
|
|
438
|
+
};
|
|
439
|
+
export type KindSpec = {
|
|
440
|
+
required: readonly string[];
|
|
441
|
+
optional: readonly string[];
|
|
442
|
+
pathParams: readonly string[];
|
|
443
|
+
locked?: true;
|
|
444
|
+
verdictClass: string;
|
|
445
|
+
shape: string;
|
|
446
|
+
asserts: string;
|
|
447
|
+
};
|