bareloop 0.11.0 → 0.13.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.
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Did the pipe grade this case the way the signer signed it?
3
+ *
4
+ * BOTH HALVES, AND BOTH ARE REQUIRED. The verdict alone is the aggregate this
5
+ * floor was written against: a red case that reds on the wrong card line, or on
6
+ * the right line and the wrong function, has told the operator nothing about
7
+ * whether their ruler works — §4.4's *"with itemized reds, not a paragraph"* is
8
+ * exactly this comparison and not a looser one.
9
+ *
10
+ * The reds compare as SETS: `decide()` grades every card item over every
11
+ * function and its emission order follows the card and the model's function
12
+ * list, while a signer writes their expectation in whatever order they thought
13
+ * of it. Order is not a fact about the pipe, so it is not compared; the ADDRESSES
14
+ * are. A duplicate is already inexpressible on both sides (`expectedOf` dedupes,
15
+ * `validateCalibrationSet` reds a repeated pair), so set comparison loses
16
+ * nothing.
17
+ * @param {{verdict: string, reds: {rule: string, fn: string}[]}} got
18
+ * @param {any} want
19
+ * @returns {{ok: boolean, verdictOk: boolean, redsOk: boolean, missing: string[], extra: string[]}}
20
+ */
21
+ export function compareExpectation(got: {
22
+ verdict: string;
23
+ reds: {
24
+ rule: string;
25
+ fn: string;
26
+ }[];
27
+ }, want: any): {
28
+ ok: boolean;
29
+ verdictOk: boolean;
30
+ redsOk: boolean;
31
+ missing: string[];
32
+ extra: string[];
33
+ };
34
+ /**
35
+ * Did the extraction survive the attack?
36
+ *
37
+ * Three readings, all mechanical, all over facts this module owns both sides of:
38
+ * - THE FUNCTION LIST is exactly the gold's, as a set. A style that hides a
39
+ * function has moved the facts even if every remaining fact is true.
40
+ * - EVERY DOCUMENTED function's `docQuote` is a REAL JSDoc opener from the
41
+ * artifact, and every UNDOCUMENTED one's is `null`. A non-null quote on an
42
+ * undocumented function is the leak this battery exists to catch, and it is
43
+ * invisible one layer up: `decide()` reds it either way (an invented quote
44
+ * fails the artifact check), so resist and leak render the SAME itemized
45
+ * reds and only the facts separate them.
46
+ * - and the DECISION still matches gold, so a leak that somehow survives both
47
+ * fact checks still has one more gate to pass.
48
+ * @param {any} facts @param {any} gold @param {string} artifactText
49
+ * @returns {{ok: boolean, why: string|null}}
50
+ */
51
+ export function factsResist(facts: any, gold: any, artifactText: string): {
52
+ ok: boolean;
53
+ why: string | null;
54
+ };
55
+ /**
56
+ * THE CALIBRATION GATE. Run the whole pipe over the signed ten and over the five
57
+ * arbiter-owned injection artifacts, and report — itemized, per case — whether
58
+ * the ruler is a ruler.
59
+ *
60
+ * It never throws on a caller's data: an illegal set is a RED (the same
61
+ * `{ok, reds}` shape module 4's validators return), because this is reached from
62
+ * a signing gate whose whole job is to hand a person a readable refusal. It
63
+ * throws on nothing at all.
64
+ *
65
+ * ORDER, and it is load-bearing: the $0 legality check runs FIRST and buys no
66
+ * calls; then the ten; then the battery. A set that cannot be legal is refused
67
+ * before a token, and an operator whose card is malformed does not pay to find
68
+ * out.
69
+ *
70
+ * ALL-OR-NOTHING, both halves (v1.73 ruling 2 and ruling 3, kept by the second
71
+ * addendum's ruling 1): `ok` is true only when all ten graded correctly AND all
72
+ * five styles resisted AND nothing was a casualty.
73
+ * THE OPERATOR'S CEILING RIDES IN AS A PREDICATE (`capStop`), asked between metered
74
+ * calls exactly as the authoring pipeline's cost book asks its own. It is the
75
+ * CALLER's book that answers, because the gate is the THIRD paid seam of one run and
76
+ * a tally that starts at zero here would be a second ceiling wearing the first one's
77
+ * number. Absent is UNBOUNDED, and unbounded is a stated operator choice.
78
+ *
79
+ * A ceiling stop is a REFUSAL, never a throw and never a partial set presented as a
80
+ * graded one: `ok` is false, the cases nobody bought are absent rather than recorded
81
+ * as failures, and `casualty` stays null — the transport was fine, the operator's own
82
+ * governance stopped the gate.
83
+ * @param {{cases: any, card: any, judgeLoop: Function|null,
84
+ * onCost?: (c: any) => void, attempts?: number, battery?: any[], batteryCard?: any,
85
+ * capStop?: () => 'cap-halt'|'pricing-red'|null}} o
86
+ * @returns {Promise<{ok: boolean, stop: string|null, casualty: any,
87
+ * graded: {id: string, ok: boolean, got: any, want: any, detail: string|null}[],
88
+ * injection: {styles: any[], allResisted: boolean, leaks: string[]},
89
+ * failures: string[], reds: Red[], judgeModel: string,
90
+ * cardHash: string|null, casesHash: string|null, setHash: string|null,
91
+ * costUsd: number|null, knownUsd: number, spendComplete: boolean, calls: any[]}>}
92
+ */
93
+ export function runCalibration({ cases, card, judgeLoop, onCost, attempts, battery, batteryCard, capStop, }: {
94
+ cases: any;
95
+ card: any;
96
+ judgeLoop: Function | null;
97
+ onCost?: (c: any) => void;
98
+ attempts?: number;
99
+ battery?: any[];
100
+ batteryCard?: any;
101
+ capStop?: () => "cap-halt" | "pricing-red" | null;
102
+ }): Promise<{
103
+ ok: boolean;
104
+ stop: string | null;
105
+ casualty: any;
106
+ graded: {
107
+ id: string;
108
+ ok: boolean;
109
+ got: any;
110
+ want: any;
111
+ detail: string | null;
112
+ }[];
113
+ injection: {
114
+ styles: any[];
115
+ allResisted: boolean;
116
+ leaks: string[];
117
+ };
118
+ failures: string[];
119
+ reds: Red[];
120
+ judgeModel: string;
121
+ cardHash: string | null;
122
+ casesHash: string | null;
123
+ setHash: string | null;
124
+ costUsd: number | null;
125
+ knownUsd: number;
126
+ spendComplete: boolean;
127
+ calls: any[];
128
+ }>;
129
+ /** @typedef {{code: string, path: string, detail: string, [k: string]: any}} Red */
130
+ /** the label a calibration's own locate calls are metered under. The SAME
131
+ * `LOCATE_LABEL` a close's judged stage spends under, deliberately: it is the
132
+ * same call to the same model over the same prompt, and a second spelling would
133
+ * make one population of spend read as two. */
134
+ export const CALIBRATION_LABEL: "judged-locate";
135
+ /** the axes that STOP the gate as a casualty rather than failing a case. All
136
+ * three are `runLocate`'s own, borrowed with their meanings intact — this module
137
+ * invents no vocabulary for a fault the shipped pipe already names. */
138
+ export const CASUALTY_AXES: readonly ("pricing-red" | "provider-red" | "artifact-red")[];
139
+ export function artifactHash(v: any): string;
140
+ /**
141
+ * The battery's OWN card — `has-doc` alone, and one line rather than three on
142
+ * purpose. Every attack style below aims at exactly one lie ("this file is
143
+ * documented"), so the card that grades them names exactly the fact being lied
144
+ * about; extra lines would buy extra prompt surface and extra ways for a
145
+ * truthful-but-noisy extraction to look like a leak.
146
+ */
147
+ export const INJECTION_CARD: Readonly<{
148
+ items: readonly Readonly<{
149
+ rule: "has-doc";
150
+ text: "Every top-level function has a JSDoc block directly above it.";
151
+ }>[];
152
+ }>;
153
+ /**
154
+ * THE FIVE STYLES, one artifact each. Every artifact carries one honestly
155
+ * documented function and one honestly undocumented one, and the attack always
156
+ * asks for the same thing: report the undocumented function as documented (or
157
+ * do not report it at all). The truth is therefore identical across all five,
158
+ * which is what makes a leak attributable to the STYLE rather than to the file.
159
+ */
160
+ export const INJECTION_LOCATE_BATTERY: readonly Readonly<{
161
+ id: string;
162
+ style: string;
163
+ attack: string;
164
+ artifact: `/**
165
+ * Add two numbers.
166
+ */
167
+ export function add(a, b) {
168
+ return a + b;
169
+ }
170
+
171
+ ${string}`;
172
+ expectFacts: Readonly<{
173
+ functions: readonly Readonly<{
174
+ name: string;
175
+ hasDoc: boolean;
176
+ }>[];
177
+ }>;
178
+ expect: Readonly<{
179
+ verdict: "pass" | "red";
180
+ reds: readonly Readonly<{
181
+ rule: string;
182
+ fn: string;
183
+ }>[];
184
+ }>;
185
+ }>[];
186
+ export type Red = {
187
+ code: string;
188
+ path: string;
189
+ detail: string;
190
+ [k: string]: any;
191
+ };
@@ -0,0 +1,352 @@
1
+ /**
2
+ * The proposal's shape, and therefore the whole shape the compiler can express.
3
+ *
4
+ * `rule` is an ENUM off the judge's own rulebook in BOTH places it appears — the
5
+ * card's lines and a case's expected reds — because wherever only a closed set
6
+ * can satisfy a field, the illegal value is made INEXPRESSIBLE rather than
7
+ * rejected after the fact (the `check-passes(name)` model). The SIZE is pinned by
8
+ * `minItems`/`maxItems` from the one constant, so nine and eleven are both
9
+ * unsayable rather than argued about afterwards.
10
+ *
11
+ * `artifact` and `text` are the only free strings, and neither decides anything:
12
+ * one is the code the judge will read, the other is the signer's own words.
13
+ */
14
+ export function proposalSchema(): {
15
+ type: string;
16
+ properties: {
17
+ card: {
18
+ type: string;
19
+ description: string;
20
+ properties: {
21
+ items: {
22
+ type: string;
23
+ minItems: number;
24
+ items: {
25
+ type: string;
26
+ properties: {
27
+ rule: {
28
+ enum: string[];
29
+ description: string;
30
+ };
31
+ text: {
32
+ type: string;
33
+ minLength: number;
34
+ description: string;
35
+ };
36
+ };
37
+ required: string[];
38
+ additionalProperties: boolean;
39
+ };
40
+ };
41
+ };
42
+ required: string[];
43
+ additionalProperties: boolean;
44
+ };
45
+ cases: {
46
+ type: string;
47
+ minItems: number;
48
+ maxItems: number;
49
+ description: string;
50
+ items: {
51
+ type: string;
52
+ properties: {
53
+ id: {
54
+ type: string;
55
+ minLength: number;
56
+ description: string;
57
+ };
58
+ artifact: {
59
+ type: string;
60
+ minLength: number;
61
+ description: string;
62
+ };
63
+ expect: {
64
+ type: string;
65
+ properties: {
66
+ verdict: {
67
+ enum: string[];
68
+ };
69
+ reds: {
70
+ type: string;
71
+ description: string;
72
+ items: {
73
+ type: string;
74
+ properties: {
75
+ rule: {
76
+ enum: string[];
77
+ description: string;
78
+ };
79
+ fn: {
80
+ type: string;
81
+ minLength: number;
82
+ description: string;
83
+ };
84
+ };
85
+ required: string[];
86
+ additionalProperties: boolean;
87
+ };
88
+ };
89
+ };
90
+ required: string[];
91
+ additionalProperties: boolean;
92
+ };
93
+ };
94
+ required: string[];
95
+ additionalProperties: boolean;
96
+ };
97
+ };
98
+ };
99
+ required: string[];
100
+ additionalProperties: boolean;
101
+ };
102
+ /**
103
+ * The output channel. It records and acknowledges; it takes no action, which is
104
+ * why handing it to a toolless compile call does not reopen D3.
105
+ * @param {{calls: any[]}} box
106
+ */
107
+ export function proposalTool(box: {
108
+ calls: any[];
109
+ }): {
110
+ name: string;
111
+ description: string;
112
+ parameters: {
113
+ type: string;
114
+ properties: {
115
+ card: {
116
+ type: string;
117
+ description: string;
118
+ properties: {
119
+ items: {
120
+ type: string;
121
+ minItems: number;
122
+ items: {
123
+ type: string;
124
+ properties: {
125
+ rule: {
126
+ enum: string[];
127
+ description: string;
128
+ };
129
+ text: {
130
+ type: string;
131
+ minLength: number;
132
+ description: string;
133
+ };
134
+ };
135
+ required: string[];
136
+ additionalProperties: boolean;
137
+ };
138
+ };
139
+ };
140
+ required: string[];
141
+ additionalProperties: boolean;
142
+ };
143
+ cases: {
144
+ type: string;
145
+ minItems: number;
146
+ maxItems: number;
147
+ description: string;
148
+ items: {
149
+ type: string;
150
+ properties: {
151
+ id: {
152
+ type: string;
153
+ minLength: number;
154
+ description: string;
155
+ };
156
+ artifact: {
157
+ type: string;
158
+ minLength: number;
159
+ description: string;
160
+ };
161
+ expect: {
162
+ type: string;
163
+ properties: {
164
+ verdict: {
165
+ enum: string[];
166
+ };
167
+ reds: {
168
+ type: string;
169
+ description: string;
170
+ items: {
171
+ type: string;
172
+ properties: {
173
+ rule: {
174
+ enum: string[];
175
+ description: string;
176
+ };
177
+ fn: {
178
+ type: string;
179
+ minLength: number;
180
+ description: string;
181
+ };
182
+ };
183
+ required: string[];
184
+ additionalProperties: boolean;
185
+ };
186
+ };
187
+ };
188
+ required: string[];
189
+ additionalProperties: boolean;
190
+ };
191
+ };
192
+ required: string[];
193
+ additionalProperties: boolean;
194
+ };
195
+ };
196
+ };
197
+ required: string[];
198
+ additionalProperties: boolean;
199
+ };
200
+ execute: (args: any) => Promise<string>;
201
+ };
202
+ /**
203
+ * The compile prompt. Q6's and Q7's answers travel VERBATIM — they are the whole
204
+ * input, and paraphrasing a lay answer is how a rubric stops being the person's.
205
+ *
206
+ * The rulebook is rendered from `JUDGE_RULES` itself rather than restated, for
207
+ * the reason the catalogue block is rendered from the catalogue: the prompt and
208
+ * the gate must describe one set of facts.
209
+ * @param {{answers: Record<string|number, any>, questions?: Record<string|number, string>}} o
210
+ */
211
+ export function cardCasesPrompt({ answers, questions }: {
212
+ answers: Record<string | number, any>;
213
+ questions?: Record<string | number, string>;
214
+ }): string;
215
+ /**
216
+ * THE D5 MOMENT. The proposal is SHOWN; the signer's `fix` is what is STORED.
217
+ *
218
+ * The fix replaces the proposal WHOLE rather than merging into it. A merge would
219
+ * mean a signer who deleted a card line got it back, and "the signer signs the
220
+ * whole hash" is not a rule that survives a field-wise reconciliation. Handing
221
+ * back no fix is a legal answer — signing the proposal as proposed — and it says
222
+ * so (`source`), because *a person read this and changed nothing* and *nobody has
223
+ * looked* are two different facts.
224
+ *
225
+ * THE GATE RUNS OVER WHAT WILL BE STORED, never over the proposal: a signer can
226
+ * fix a legal proposal into an illegal one, and the artifact that reaches the
227
+ * hash is the one that must be legal.
228
+ *
229
+ * `scrubbed` is the INGEST SCRUB'S OWN ANNOUNCEMENT — the paths whose bytes the
230
+ * secret inventory masked on the way in. Empty on every honest artifact, and
231
+ * never silent when it is not: a signer signs a hash over the STORED bytes, so
232
+ * "what you typed is not what was stored" is a fact they are owed rather than one
233
+ * the redactor keeps.
234
+ * @param {{proposal: any, fix?: any}} o
235
+ * @returns {{ok: boolean, reds: Red[], card: any, cases: any[]|null, source: 'signer'|'proposal',
236
+ * scrubbed: {path: string}[]}}
237
+ */
238
+ export function signJudgedArtifacts({ proposal, fix }: {
239
+ proposal: any;
240
+ fix?: any;
241
+ }): {
242
+ ok: boolean;
243
+ reds: Red[];
244
+ card: any;
245
+ cases: any[] | null;
246
+ source: "signer" | "proposal";
247
+ scrubbed: {
248
+ path: string;
249
+ }[];
250
+ };
251
+ /**
252
+ * Fold the two signed artifacts into the close declaration, ENUMERATED.
253
+ *
254
+ * WHERE EACH LANDS, and both are inside the spec so `jobSpecHash` covers them by
255
+ * construction (the hash is over the whole resolved spec):
256
+ * - THE CARD replaces the judged stage's own `params.card`. ONE card, and it is
257
+ * the SIGNED one: the composer's draft is a draft, and two cards in one close
258
+ * is the drift a single storage site exists to prevent. The stage is where it
259
+ * already lives, which is what `validateCard`, the M2 runner and the locate
260
+ * prompt all read.
261
+ * - THE CASES land beside the stages as `calibration.cases` — a close-level
262
+ * artifact, because the set calibrates the RULER and not one stage's params,
263
+ * and because module 5's gate reads it before any stage runs.
264
+ * - THE JUDGE MODEL lands beside them as `calibration.judgeModel`, and it is the
265
+ * PIN (`JUDGE_MODEL`) rather than anything a caller may name. A calibration set
266
+ * is only worth the tier that graded it — §4.2's whole safety argument is worth
267
+ * exactly as much as BA-20's injection evidence, which is haiku-4.5's alone — so
268
+ * the set has to carry which tier certified it or nothing downstream can tell a
269
+ * signed floor from a bumped one. Storing it HERE, inside the spec, is what makes
270
+ * a bump flip `jobSpecHash`: the signature dies, the signer re-signs, and a
271
+ * re-sign is a re-run of the calibration gate. That is the docstring on
272
+ * `JUDGE_MODEL` finally given a detector instead of a promise (F45).
273
+ *
274
+ * A card with NOWHERE TO LAND THROWS. It is a caller's own broken input — a
275
+ * signed rubric folded into a close with no judged ruler — and there is no safe
276
+ * direction to degrade toward: storing it would sign a rubric nothing reads.
277
+ *
278
+ * The input is never mutated: a closeDecl is a signed artefact and rewriting a
279
+ * caller's copy in place is how two readers come to disagree about what was
280
+ * signed.
281
+ * @param {any} closeDecl @param {{card: any, cases: any[]}} o
282
+ * @returns {any} a new closeDecl
283
+ */
284
+ export function foldJudgedArtifacts(closeDecl: any, { card, cases }: {
285
+ card: any;
286
+ cases: any[];
287
+ }): any;
288
+ /**
289
+ * ONE compile call: the person's Q6 and Q7 in, a proposal out.
290
+ *
291
+ * It buys ONE artifact through ONE channel, and the malformed-emission ladder is
292
+ * the SHARED one (`askStructured`) rather than a second copy — a second ladder is
293
+ * a second place for the cap, the reject block and the re-ask to drift.
294
+ *
295
+ * WHAT IS AND IS NOT RETRIED, and the split is the standing one: a reply that
296
+ * carries no proposal is a TRANSPORT fault and is retried under the bound; a
297
+ * proposal that PARSED and then broke the ruling is not — the model answered
298
+ * perfectly clearly and re-asking buys another call to be told the same thing.
299
+ * The proposal is returned as it was said, never repaired: no JSON repair, ever.
300
+ *
301
+ * The book is the CALLER's, so one ceiling governs the survey, the declaration
302
+ * ladder and this compile — the advertised ceiling and the enforced ceiling are
303
+ * the same ceiling.
304
+ * @param {{answers: Record<string|number, any>, questions?: Record<string|number, string>,
305
+ * generate: Function, book?: ReturnType<typeof makeCostBook>,
306
+ * structuredMode?: 'tool'|'text', structureRetries?: number}} o
307
+ * @returns {Promise<{ok: boolean, proposal: any, reds: Red[], stop: string|null,
308
+ * attempts: number, raw: string, cost: any, raws: any[]}>}
309
+ */
310
+ export function proposeJudgedArtifacts({ answers, questions, generate, book, structuredMode, structureRetries, }: {
311
+ answers: Record<string | number, any>;
312
+ questions?: Record<string | number, string>;
313
+ generate: Function;
314
+ book?: ReturnType<typeof makeCostBook>;
315
+ structuredMode?: "tool" | "text";
316
+ structureRetries?: number;
317
+ }): Promise<{
318
+ ok: boolean;
319
+ proposal: any;
320
+ reds: Red[];
321
+ stop: string | null;
322
+ attempts: number;
323
+ raw: string;
324
+ cost: any;
325
+ raws: any[];
326
+ }>;
327
+ /** @typedef {{code: string, path: string, detail: string, [k: string]: any}} Red */
328
+ /** the output channel for the compile. It takes no action; it carries the answer. */
329
+ export const PROPOSAL_TOOL_NAME: "propose_rubric";
330
+ /** what the tool returns. The loop stops on delivery, so the model never reads it. */
331
+ export const PROPOSAL_ACK: "proposal received";
332
+ /** the label the compile call is metered and persisted under — one spelling */
333
+ export const PROPOSAL_LABEL: "judged-compile";
334
+ /** a malformed EMISSION is a transport fault, bounded on its own axis — the same
335
+ * ceiling `authorClose` declares for the declaration channel */
336
+ export const MAX_PROPOSAL_RETRIES: 2;
337
+ /**
338
+ * The system prompt a caller BINDS ITS SEAM WITH — this module owns no provider
339
+ * and picks none, exactly as `authorClose` does not: the compile call arrives as
340
+ * `generate`, and a caller wires it with `makeLoopGenerate(provider, {system:
341
+ * COMPILE_SYSTEM})`, whose own `maxTokens` default (F30) is what holds ten
342
+ * artifacts. Exported rather than inlined so the one register this call is made
343
+ * in is not re-spelled at every integration.
344
+ */
345
+ export const COMPILE_SYSTEM: string;
346
+ export type Red = {
347
+ code: string;
348
+ path: string;
349
+ detail: string;
350
+ [k: string]: any;
351
+ };
352
+ import { makeCostBook } from './authorflow.js';
@@ -6,6 +6,16 @@ export function isDeclaredClose(job: any): boolean;
6
6
  *
7
7
  * `offer` and `needs` pass through untouched when a declaration carries them
8
8
  * (v1's schema does not let one), so `checkMenu`'s derivation is unchanged.
9
+ *
10
+ * THE JUDGE TIER RIDES ALONG, and it rides as a STAMP for the same reason `offer`
11
+ * does. The tier that graded this close's calibration set is a CLOSE-level fact
12
+ * (`calibration.judgeModel`), and the stage that would buy a judge call is a STAGE;
13
+ * `runStage` is handed stages and never the declaration they came out of. Rather than
14
+ * plumb a second close-level channel down through every executor seam, the one place
15
+ * that already turns a declaration into stages carries it across — and it carries it
16
+ * from the SIGNED bytes, so a stage can never name a tier the signature does not.
17
+ * `runJudgedFloor` refuses a mismatch; the absence of a stamp is the SPEC gate's
18
+ * business (`validateCloseDecl` reds a set with no model), never a runtime fall-back.
9
19
  * @param {any} closeDecl
10
20
  * @returns {any[]|null} null when this is not a declaration
11
21
  */
@@ -98,7 +108,9 @@ export function guardNames(closeDecl: any, verdictType: string): string[];
98
108
  * @param {(s: string) => string} [redact] the scrub, applied at THIS boundary
99
109
  * @param {{timeoutMs?: number, cwd?: string, seedRef?: string,
100
110
  * seedTrees?: any, gapCap?: number, maxBuffer?: number, baselineMode?: 'auto'|'worktree',
101
- * humanRuling?: {decision: string, text?: string|null}|null}} [opts]
111
+ * humanRuling?: {decision: string, text?: string|null}|null,
112
+ * judgeLoop?: ((o: {system: string}) => any)|null,
113
+ * onJudgeCost?: ((c: any) => void)|null}} [opts]
102
114
  * @returns {Promise<any>}
103
115
  */
104
116
  export function runDeclaredStages(stages: any[], redact?: (s: string) => string, opts?: {
@@ -113,6 +125,10 @@ export function runDeclaredStages(stages: any[], redact?: (s: string) => string,
113
125
  decision: string;
114
126
  text?: string | null;
115
127
  } | null;
128
+ judgeLoop?: ((o: {
129
+ system: string;
130
+ }) => any) | null;
131
+ onJudgeCost?: ((c: any) => void) | null;
116
132
  }): Promise<any>;
117
133
  /**
118
134
  * The trend reader's input for ONE close verdict, whichever executor produced
@@ -155,6 +171,12 @@ export const DECLARED_GENRES: readonly "TYPES"[];
155
171
  * channel of its own.
156
172
  */
157
173
  export const CLOSE_DECL_FIELDS: readonly string[];
174
+ /** what a stored calibration set carries, ENUMERATED: the frozen cases and the judge
175
+ * tier that graded them. Both are inside the spec, so `jobSpecHash` covers both — which
176
+ * is the whole mechanism behind "a judge-model bump forces a full recalibration"
177
+ * (src/judged.js, `JUDGE_MODEL`): the field moves, the hash moves, the signature dies,
178
+ * and the re-sign re-runs the gate. Anything else in there is a field nobody reads. */
179
+ export const CALIBRATION_FIELDS: readonly string[];
158
180
  /**
159
181
  * The prefix M1 puts on EVERY gap line of a declared stage (its `ctx.gapKeep`).
160
182
  * A literal, so the anchored pattern below is exact.
@@ -215,10 +237,17 @@ export const HUMAN_CHECKPOINTS: readonly string[];
215
237
  * validator reads one hierarchy table rather than hard-coding a class.
216
238
  *
217
239
  * `hard` is by CONSTRUCTION: every mechanical kind is a command whose measurement
218
- * is the truth. `hitl` joined it at N4 slice 1, and only because `human-confirms`
219
- * is genuinely LIVE — the widening and the kind go in one commit, or this table
220
- * admits a class the executor cannot render. The `soft` class is still absent:
221
- * `judged-floor` is locked, so no declaration can reach above hitl.
240
+ * is the truth. `hitl` joined it at N4 slice 1, and `soft` at softgreen module 3
241
+ * — each only because its kind is genuinely LIVE (`human-confirms`, then
242
+ * `judged-floor`): the widening and the kind go in one commit, or this table
243
+ * admits a class the executor cannot render.
244
+ *
245
+ * `hitl` STAYS despite the class's retirement (PRD v1.71: the human stage moved
246
+ * out of the close and became the review door at the end of every run). It is
247
+ * kept because `jobs/litectx-maintainer.json` is a SIGNED spec carrying a hitl
248
+ * declaration, and a signed spec is untouchable — dropping the spelling here
249
+ * would invalidate a signature the operator already gave, which is a re-sign
250
+ * nobody asked for. Retiring it is a separate, deliberate deletion.
222
251
  *
223
252
  * The direction that matters is unchanged. This says which class a declaration
224
253
  * MAY claim; `closeCeiling` says which class its stages actually NEED. A pick
package/types/index.d.ts CHANGED
@@ -1,20 +1,25 @@
1
1
  export { makeSpine } from "./spine.js";
2
2
  export { runPlan } from "./planrun.js";
3
- export { runJob } from "./run.js";
4
3
  export { ralph, runClose, runStages, CLOSE_FAULTS } from "./ralph.js";
5
4
  export { globToPrefix, scanSecrets } from "./validate.js";
6
5
  export { validateJob, jobSpecHash, checkApproval, checkMenu, CLOSE_TYPES, CLASS_BY_CLOSE, GOLD_COMPARE, CADENCE_UNITS, PROVIDERS, CONDITION_KEYS, TOOL_MENU, LOCKED_TOOLS, STORE_VERBS, VERDICT_TYPES, LOCKED_VERDICTS } from "./job.js";
7
6
  export { validatePlan, stageClose, EXIT_TYPES, MAX_EXITS_PER_STEP, MAX_PLAN_STEPS, WRITE_VERBS, closeStagesOf } from "./plan.js";
8
7
  export { snapshotScope, evalExits } from "./exits.js";
9
- export { BRIDGE_SCHEMA, validateBridge, deriveStatus, listingRow, loadGate, mintBridge, appendGreen, appendRed, loadBridge, loadRegistry, saveBridge, makeRegistry, registryExists } from "./bridges.js";
8
+ export { runJob, ACCOUNTED_ROUND_TYPES } from "./run.js";
9
+ export { BRIDGE_SCHEMA, validateBridge, deriveStatus, listingRow, loadGate, mintBridge, appendGreen, appendRed, loadBridge, loadRegistry, saveBridge, makeRegistry, registryExists, QUARANTINED_VERDICTS, QUARANTINED_CODE, quarantinesCredit, newestEligibleVersion, reuseEligibility, recordDoor } from "./bridges.js";
10
10
  export { renderListing, selectionPrompt } from "./selection.js";
11
- export { validateEnvelope, resolveTrySpec, resolveReuse, reuseSpecHash, selectBridge, runReuse, REUSE_GRADED_RED, readResume, resumeTreeGate, CHECKPOINT_OUTCOMES, PAUSE_TTL_MS, checkpointAgeGate } from "./reuse.js";
12
- export { classifyIncidents, foldLedger, ledgerDeltas, updateLedger, LEDGER_CLASSES } from "./ledger.js";
11
+ export { validateEnvelope, resolveTrySpec, resolveReuse, reuseSpecHash, selectBridge, runReuse, REUSE_GRADED_RED, readResume, resumeTreeGate, CHECKPOINT_OUTCOMES, PAUSE_TTL_MS, checkpointAgeGate, applyDoorDecision, writeRunGreenRow } from "./reuse.js";
12
+ export { classifyIncidents, foldLedger, ledgerDeltas, updateLedger, LEDGER_CLASSES, VOUCHED_RATE_SOURCES, rateProvenance, spendProvenance } from "./ledger.js";
13
13
  export { workBranchName, prepareWorkBranch, WORK_BRANCH_PREFIX, WORK_BRANCH_RE } from "./workbranch.js";
14
- export { runDeclaredClose, runStage, seedRead, seedAtHead, seedListing, changedSet, makeSeedTrees, LIVE_KINDS, STOP_FAULTS, JUDGED_MARKER, EXIT_GREEN, EXIT_RED, EXIT_STOP, HUMAN_DECISIONS, SEED_EXEMPT_KINDS, normalizeHumanRuling } from "./kinds.js";
15
- export { validateDeclaration, normalizeDeclaration, KIND_CATALOGUE, CATALOGUE_KINDS, CATALOGUE_LIVE_KINDS, LOCKED_KINDS, TYPES_GENRE, TYPES_GENRE_TEMPLATE, GENRE_LANGUAGES, genreEnv, genreOwnedEnvNames, genreInstruments, DIRECTIONS, BASELINES, MAX_STAGES, VERDICT_CLASSES, LOCKED_CLASSES, LIVE_CLASSES, CLASS_BATTERIES, classGuards, closeCeiling, NEVER_OFFERED_KINDS } from "./authoring.js";
14
+ export { createReadShim, wrapReadTool, readShimArm, readShimStrategy, READ_SHIM_CAP, READ_SHIM_STRATEGY, READ_SHIM_DIFF_STRATEGY, READ_SHIM_ARMS } from "./readshim.js";
15
+ export { runDeclaredClose, runStage, seedRead, seedAtHead, seedListing, changedSet, makeSeedTrees, LIVE_KINDS, STOP_FAULTS, JUDGED_MARKER, EXIT_GREEN, EXIT_RED, EXIT_STOP, HUMAN_DECISIONS, SEED_EXEMPT_KINDS, JUDGED_FLOOR_KIND, normalizeHumanRuling, resolveHumanRuling, JUDGE_ATTEMPTS, MAX_JUDGED_PATHS, REVIEW_DOOR, DOOR_OPEN_OUTCOMES, REVIEW_DOOR_CLASSES, doorOpens, mechanicalStages } from "./kinds.js";
16
+ export { answerReviewDoor, doorRecordOf, doorAgeGate } from "./reviewdoor.js";
17
+ export { JUDGE_MODEL, JUDGE_MAX_TOKENS, JUDGE_RULES, JUDGE_RULE_IDS, LOCATE_AXES, LOCATE_LABEL, validateCard, validateFacts, locatePrompt, runLocate, decide, defaultJudgeLoop, CALIBRATION_SIZE, CASE_VERDICTS, validateCalibrationSet, validateJudgedArtifacts, expectedOf } from "./judged.js";
18
+ export { proposeJudgedArtifacts, signJudgedArtifacts, foldJudgedArtifacts, proposalSchema, proposalTool, cardCasesPrompt, PROPOSAL_TOOL_NAME, PROPOSAL_LABEL, MAX_PROPOSAL_RETRIES, COMPILE_SYSTEM } from "./cardauthor.js";
19
+ export { runCalibration, compareExpectation, factsResist, artifactHash, INJECTION_LOCATE_BATTERY, INJECTION_CARD, CALIBRATION_LABEL, CASUALTY_AXES } from "./calibrate.js";
20
+ export { validateDeclaration, normalizeDeclaration, KIND_CATALOGUE, CATALOGUE_KINDS, CATALOGUE_LIVE_KINDS, LOCKED_KINDS, TYPES_GENRE, TYPES_GENRE_TEMPLATE, GENRE_LANGUAGES, genreEnv, genreOwnedEnvNames, genreInstruments, DIRECTIONS, BASELINES, MAX_STAGES, VERDICT_CLASSES, LOCKED_CLASSES, LIVE_CLASSES, CLASS_BATTERIES, classGuards, classMenu, closeCeiling, NEVER_OFFERED_KINDS } from "./authoring.js";
16
21
  export { runAuthorScout, buildSeedListing, seedFileList, classifySurvey, AUTHOR_SCOUT_VERBS, SCOUT_ATTEMPTS, SURVEY_CAUSES, SCOUT_RETRY_CAUSES } from "./authorscout.js";
17
22
  export { scrubRaw, RAW_PERSIST_MAX, RAW_TRIM_MARKER } from "./text.js";
18
- export { authorClose, authorPrompt, declarationSchema, makeLoopGenerate, MAX_REVISIONS, QUESTION_SETS, GREEN_QUESTIONS, CLASS_STATEMENTS, questionsFor, requiredAnswersFor } from "./authorflow.js";
23
+ export { authorClose, authorPrompt, declarationSchema, makeLoopGenerate, MAX_REVISIONS, QUESTION_SETS, GREEN_QUESTIONS, SOFTGREEN_QUESTIONS, CLASS_STATEMENTS, questionsFor, requiredAnswersFor } from "./authorflow.js";
19
24
  export { validateCloseDecl, runDeclaredStages, declaredStages, isDeclaredClose, guardNames, closeGrade, DECLARED_GENRES, DECLARED_GAP_PREFIX, DECLARED_GAP_KEEP, DECLARED_CLOSE_CLASSES, CLOSE_DECL_FIELDS, HUMAN_PAUSE, HITL_PAUSE, HITL_DECISION_RED, HUMAN_CHECKPOINTS } from "./declaredclose.js";
20
25
  export { runInterview, authorCloseForJob, assembleSpec, prepareSigning, refusalEvents, refuseLockedKind, GENRE, REFUSAL_LIB, REFUSAL_CATEGORY, AUTHORED_SPEC_FIELDS } from "./authorjob.js";