bareloop 0.22.0 → 0.24.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 +247 -0
- package/README.md +1 -1
- package/bareloop.context.md +113 -29
- package/package.json +2 -2
- package/src/authorflow.js +24 -9
- package/src/authoring.js +32 -0
- package/src/authorjob.js +108 -36
- package/src/authorscout.js +83 -9
- package/src/calibrate.js +43 -12
- package/src/cardauthor.js +23 -16
- package/src/cli.js +73 -21
- package/src/declaredclose.js +25 -11
- package/src/index.js +8 -5
- package/src/job.js +92 -2
- package/src/judged.js +240 -19
- package/src/kinds.js +89 -12
- package/src/planrun.js +194 -41
- package/src/providers.js +301 -0
- package/src/ratelimit.js +116 -0
- package/src/reuse.js +9 -1
- package/src/run.js +68 -9
- package/src/transport.js +29 -12
- package/src/validate.js +4 -0
- package/types/authoring.d.ts +30 -0
- package/types/authorjob.d.ts +10 -6
- package/types/authorscout.d.ts +27 -2
- package/types/calibrate.d.ts +9 -2
- package/types/cardauthor.d.ts +13 -11
- package/types/cli.d.ts +2 -1
- package/types/declaredclose.d.ts +8 -1
- package/types/index.d.ts +1 -1
- package/types/job.d.ts +25 -0
- package/types/judged.d.ts +130 -16
- package/types/kinds.d.ts +51 -3
- package/types/planrun.d.ts +10 -2
- package/types/providers.d.ts +166 -0
- package/types/ratelimit.d.ts +59 -0
- package/types/run.d.ts +17 -3
- package/types/transport.d.ts +10 -4
package/types/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { workBranchName, prepareWorkBranch, WORK_BRANCH_PREFIX, WORK_BRANCH_RE }
|
|
|
15
15
|
export { createReadShim, wrapReadTool, readShimArm, readShimStrategy, READ_SHIM_CAP, READ_SHIM_STRATEGY, READ_SHIM_DIFF_STRATEGY, READ_SHIM_ARMS } from "./readshim.js";
|
|
16
16
|
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";
|
|
17
17
|
export { answerReviewDoor, doorRecordOf, doorAgeGate } from "./reviewdoor.js";
|
|
18
|
-
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 { JUDGE_MODEL, resolveJudge, 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";
|
|
19
19
|
export { proposeJudgedArtifacts, signJudgedArtifacts, foldJudgedArtifacts, proposalSchema, proposalTool, cardCasesPrompt, PROPOSAL_TOOL_NAME, PROPOSAL_LABEL, MAX_PROPOSAL_RETRIES, COMPILE_SYSTEM } from "./cardauthor.js";
|
|
20
20
|
export { runCalibration, compareExpectation, factsResist, artifactHash, INJECTION_LOCATE_BATTERY, INJECTION_CARD, CALIBRATION_LABEL, CASUALTY_AXES } from "./calibrate.js";
|
|
21
21
|
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";
|
package/types/job.d.ts
CHANGED
|
@@ -207,6 +207,31 @@ export const CADENCE_UNITS: readonly string[];
|
|
|
207
207
|
* subscription — its costUsd axis is NOTIONAL (API-equivalent value, not
|
|
208
208
|
* billed), so it is a DISTINCT condition: rows never pool with anthropic-api
|
|
209
209
|
* rows on the cost axis, and budgets sized for one do not transfer. */
|
|
210
|
+
/** PRD item 28 (2026-09-06/09-09): `openai-api` — an OpenAI-shaped provider,
|
|
211
|
+
* constructed via `src/providers.js`'s factory. hamr's ruling (PRD 30.7):
|
|
212
|
+
* `deepseek-chat` is THE secondary provider (one, not a menu of half-tested
|
|
213
|
+
* models); the factory's tier table is where that lives, not this menu.
|
|
214
|
+
*
|
|
215
|
+
* PRD item 31.3 (hamr, 2026-09-09: *"anthropic, openai, gemini drop ollama for
|
|
216
|
+
* now"*): `gemini-api` joins. That is bareloop matching bare-agent's own
|
|
217
|
+
* adapter surface rather than curating a shorter list — bare-agent exports four
|
|
218
|
+
* real HTTP backends (Anthropic, OpenAI, Gemini, Ollama) plus CLIPipe and the
|
|
219
|
+
* FallbackProvider composite; `provider-http.js`, `provider-stop-reason.js`,
|
|
220
|
+
* `provider-temperature.js` and `provider-usage.js` are shared HELPERS, not
|
|
221
|
+
* backends, and were miscounted as providers once — the export list, never the
|
|
222
|
+
* filenames, is the source of truth.
|
|
223
|
+
*
|
|
224
|
+
* Ollama is deliberately NOT here. Beyond hamr's word, it is the one entry
|
|
225
|
+
* whose economics differ in kind: it takes no API key and bills nothing, so
|
|
226
|
+
* every round would price at $0 through machinery that treats $0 as a real
|
|
227
|
+
* price. An unpriced round reported as free is the exact honesty violation the
|
|
228
|
+
* `?? 0` rule exists to stop, and admitting it needs that question answered
|
|
229
|
+
* first, not a menu entry.
|
|
230
|
+
*
|
|
231
|
+
* `gemini-api` is ADMITTED-PENDING-PROBE: the probe rule stands (item 28
|
|
232
|
+
* ruling (d)) and gemini has zero runs. See `PROBE_STATUS` in
|
|
233
|
+
* `src/providers.js` — a spec may name it, and the runner says out loud that
|
|
234
|
+
* nothing has proven it. */
|
|
210
235
|
export const PROVIDERS: readonly string[];
|
|
211
236
|
/** V3 environment label: declared keys only — every field is a lineage-key
|
|
212
237
|
* candidate at N3. `provider` is part of the key by definition (top-level,
|
package/types/judged.d.ts
CHANGED
|
@@ -1,3 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RESOLVE WHICH MODEL GRADES THIS JOB (PRD item 32.1).
|
|
3
|
+
*
|
|
4
|
+
* hamr, 2026-09-10: *"what i care about is that judge becomes llm agnostic and
|
|
5
|
+
* not set to one model or provider"* — and the shape he named: *"defaults to
|
|
6
|
+
* whatever llm is used and can be overriden"*.
|
|
7
|
+
*
|
|
8
|
+
* So, in precedence order:
|
|
9
|
+
* 1. `spec.judge` — an explicit, SIGNED `{provider, model}`. This is how a run
|
|
10
|
+
* pins a judge deliberately different from its worker (an independent
|
|
11
|
+
* reader, or a judge whose calibration a job wants to keep while the worker
|
|
12
|
+
* moves). It is a spec field the HUMAN signs, part of `jobSpecHash` like
|
|
13
|
+
* every other; the drafting agent cannot express it, because naming your
|
|
14
|
+
* own examiner is arbiter territory.
|
|
15
|
+
* 2. otherwise the job's OWN worker provider and model. A DeepSeek job judges
|
|
16
|
+
* on DeepSeek and needs no second account — which is the whole point: after
|
|
17
|
+
* item 31.4 a green job runs on its own key alone, and this is what lets a
|
|
18
|
+
* JUDGED one do the same.
|
|
19
|
+
*
|
|
20
|
+
* There is deliberately NO third fallback to `JUDGE_MODEL`. A caller that cannot
|
|
21
|
+
* say which model will grade has not wired a judge, and the grading path stops
|
|
22
|
+
* as a wiring gap rather than grading under an identity nobody chose — the same
|
|
23
|
+
* answer an absent `judgeLoop` already gets. A silent default here would be the
|
|
24
|
+
* exact silent-ignore class that `endpointKey` and F149 exist to prevent, except
|
|
25
|
+
* pointed at the arbiter.
|
|
26
|
+
*
|
|
27
|
+
* SELF-GRADING is licensed by measurement, not by this function: the judge
|
|
28
|
+
* renders no verdict (it locates facts; `decide()` is deterministic), and the
|
|
29
|
+
* calibration gate — 10 cases, a 10-of-10 floor, no partial credit, cases that
|
|
30
|
+
* MUST fail — is exactly the instrument that catches a judge which cannot see
|
|
31
|
+
* failures. If a worker-family judge cannot pass its own calibration, that is
|
|
32
|
+
* the finding, and the gate refuses to sign.
|
|
33
|
+
*
|
|
34
|
+
* @param {{specJudge?: any, workerProvider?: string, workerModel?: string}} o
|
|
35
|
+
* @returns {{provider: string, model: string}}
|
|
36
|
+
*/
|
|
37
|
+
export function resolveJudge({ specJudge, workerProvider, workerModel }?: {
|
|
38
|
+
specJudge?: any;
|
|
39
|
+
workerProvider?: string;
|
|
40
|
+
workerModel?: string;
|
|
41
|
+
}): {
|
|
42
|
+
provider: string;
|
|
43
|
+
model: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* `resolveJudge` needs a worker MODEL already resolved, and an authoring
|
|
47
|
+
* pipeline has to compute one identity at TWO different moments — once at
|
|
48
|
+
* compose time, to STAMP `closeDecl.calibration.judgeModel` into the spec it
|
|
49
|
+
* is about to sign, and again at the calibration gate that grades against
|
|
50
|
+
* that stamp — from a value that is not yet a validated spec (the operator's
|
|
51
|
+
* draft) the first time and is one (the assembled spec) the second. Two
|
|
52
|
+
* hand-spelled compositions of `resolveWorkerModel` + `resolveJudge` is
|
|
53
|
+
* exactly the kind of pair that drifts (PRD F45's "a rule with no detector is
|
|
54
|
+
* prose" applies to a rule spelled TWICE just as much as to one spelled
|
|
55
|
+
* nowhere) — this is the one spelling both calls make, and it mirrors the
|
|
56
|
+
* SAME composition `scripts/run-u.mjs` applies at launch time: the named
|
|
57
|
+
* provider's own `tiers.sonnet` defaults an absent model, and a signed
|
|
58
|
+
* `judge` override wins over the worker default.
|
|
59
|
+
*
|
|
60
|
+
* `source` is read for `provider`/`model`/`judge` only, so a draft and the
|
|
61
|
+
* spec `assembleSpec` folds it into resolve identically — `assembleSpec`
|
|
62
|
+
* spreads the draft into the spec untouched on those three fields — and any
|
|
63
|
+
* draft that goes on to validate and sign therefore stamps and grades under
|
|
64
|
+
* the exact same identity `scripts/run-u.mjs` will resolve at run time.
|
|
65
|
+
*
|
|
66
|
+
* `source.provider` absent, or unresolvable, or `source.judge` malformed all
|
|
67
|
+
* THROW here exactly as `resolveProvider`/`resolveJudge` already do on their
|
|
68
|
+
* own — a caller composing this from a pre-validation draft is expected to
|
|
69
|
+
* catch that and use a placeholder, because a draft that cannot resolve here
|
|
70
|
+
* is a draft `validateJob` reds a few lines later regardless, before anything
|
|
71
|
+
* gets signed under the placeholder.
|
|
72
|
+
*
|
|
73
|
+
* `resolveWorkerModelFn` is taken as a PARAMETER rather than imported — this
|
|
74
|
+
* module cannot import `./job.js` directly: `job.js` imports
|
|
75
|
+
* `./declaredclose.js`, which imports `resolveJudge` from THIS module, and a
|
|
76
|
+
* `judged.js` → `job.js` edge would close that into a cycle. `resolveProvider`
|
|
77
|
+
* has no such conflict (`./providers.js` imports nothing local) and is
|
|
78
|
+
* imported directly.
|
|
79
|
+
*
|
|
80
|
+
* @param {{provider?: string, model?: string, judge?: any}} source draft or spec
|
|
81
|
+
* @param {string} fallbackProviderName used only when `source.provider` is absent
|
|
82
|
+
* @param {(o: {specModel?: string, flagModel?: string, defaultModel: string}) => {model: string, source: string}} resolveWorkerModelFn `resolveWorkerModel` from `./job.js`
|
|
83
|
+
* @returns {{provider: string, model: string}}
|
|
84
|
+
*/
|
|
85
|
+
export function resolveJobJudge(source: {
|
|
86
|
+
provider?: string;
|
|
87
|
+
model?: string;
|
|
88
|
+
judge?: any;
|
|
89
|
+
}, fallbackProviderName: string, resolveWorkerModelFn: (o: {
|
|
90
|
+
specModel?: string;
|
|
91
|
+
flagModel?: string;
|
|
92
|
+
defaultModel: string;
|
|
93
|
+
}) => {
|
|
94
|
+
model: string;
|
|
95
|
+
source: string;
|
|
96
|
+
}): {
|
|
97
|
+
provider: string;
|
|
98
|
+
model: string;
|
|
99
|
+
};
|
|
1
100
|
/**
|
|
2
101
|
* The rubric card: Q6's answer compiled into enumerated items, signed by the
|
|
3
102
|
* person and enumerated in the spec hash. `rule` selects from `JUDGE_RULES`;
|
|
@@ -130,12 +229,13 @@ export function locatePrompt(card: any): string;
|
|
|
130
229
|
* On every route out, red or clean, `onCost` fires exactly once with the honest
|
|
131
230
|
* read: a paid call that leaves no meter record is F12 wearing a judge's coat.
|
|
132
231
|
* @param {{artifactText: string, card: any, loopFactory: (o: {provider?: any, system: string}) => any,
|
|
133
|
-
* maxTokens?: number, attempt?: number, onCost?: (c: {costUsd: number|null, unpricedRounds: number}) => void
|
|
232
|
+
* maxTokens?: number, attempt?: number, onCost?: (c: {costUsd: number|null, unpricedRounds: number}) => void,
|
|
233
|
+
* callBounds?: {timeoutMs?: number, deadlineMs?: number}}} o
|
|
134
234
|
* @returns {Promise<{ok: boolean, facts: any|null, red: {axis: string, detail: string}|null,
|
|
135
235
|
* costUsd: number|null, unpricedRounds: number, truncated: boolean, parseError: boolean,
|
|
136
236
|
* raw: ReturnType<typeof scrubRaw>}>}
|
|
137
237
|
*/
|
|
138
|
-
export function runLocate({ artifactText, card, loopFactory, maxTokens, attempt, onCost }: {
|
|
238
|
+
export function runLocate({ artifactText, card, loopFactory, maxTokens, attempt, onCost, callBounds, }: {
|
|
139
239
|
artifactText: string;
|
|
140
240
|
card: any;
|
|
141
241
|
loopFactory: (o: {
|
|
@@ -148,6 +248,10 @@ export function runLocate({ artifactText, card, loopFactory, maxTokens, attempt,
|
|
|
148
248
|
costUsd: number | null;
|
|
149
249
|
unpricedRounds: number;
|
|
150
250
|
}) => void;
|
|
251
|
+
callBounds?: {
|
|
252
|
+
timeoutMs?: number;
|
|
253
|
+
deadlineMs?: number;
|
|
254
|
+
};
|
|
151
255
|
}): Promise<{
|
|
152
256
|
ok: boolean;
|
|
153
257
|
facts: any | null;
|
|
@@ -196,25 +300,35 @@ export function decide(facts: any, card: any, { artifactText }?: {
|
|
|
196
300
|
reason: string | null;
|
|
197
301
|
};
|
|
198
302
|
/**
|
|
199
|
-
* THE JUDGE
|
|
200
|
-
* the
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
303
|
+
* THE JUDGE'S HISTORICAL PIN. Until PRD item 32 (2026-09-10) this constant WAS
|
|
304
|
+
* the judge: every grading path imported it, so bareloop could run a worker on
|
|
305
|
+
* any provider and still judge only on Claude.
|
|
306
|
+
*
|
|
307
|
+
* It is no longer read by any grading path. The judge identity is now RESOLVED
|
|
308
|
+
* per job (`resolveJudge` below) and travels as data — `ctx.judgeModel` into
|
|
309
|
+
* `runJudgedFloor`, an explicit argument into the calibration gate, and
|
|
310
|
+
* `closeDecl.calibration.judgeModel` into the signed spec, exactly as before.
|
|
311
|
+
* Keeping the export is deliberate: it is part of the public API
|
|
312
|
+
* (`src/index.js`) and an adopter importing it should not break on a minor.
|
|
313
|
+
* What it means now is "the judge bareloop pinned before item 32", which is
|
|
314
|
+
* still the right DEFAULT for an anthropic-api job and still the only tier with
|
|
315
|
+
* established injection resistance upstream (BA-20's `INJECTION_BATTERY` is
|
|
316
|
+
* haiku-4.5 only).
|
|
204
317
|
*
|
|
205
|
-
*
|
|
206
|
-
* rule with no
|
|
207
|
-
*
|
|
318
|
+
* THE ENFORCEMENT IS UNCHANGED, and still lives in three wired places because a
|
|
319
|
+
* rule with no detector is prose (F45) — only the value being compared moved
|
|
320
|
+
* from this constant to the resolved identity:
|
|
321
|
+
* 1. the identity is STORED with the set it graded — `foldJudgedArtifacts`
|
|
208
322
|
* writes it as `closeDecl.calibration.judgeModel`, inside the spec, so
|
|
209
|
-
* `jobSpecHash` covers it by construction.
|
|
323
|
+
* `jobSpecHash` covers it by construction. Change the judge and every
|
|
210
324
|
* signed judged spec hashes differently: the signature dies, and re-signing
|
|
211
325
|
* is what re-runs the calibration gate.
|
|
212
326
|
* 2. `validateCloseDecl` REQUIRES it on any stored set — a set nobody can
|
|
213
|
-
* attribute to a
|
|
214
|
-
* 3. `runJudgedFloor` refuses to grade when the stored
|
|
215
|
-
* naming both
|
|
216
|
-
* the new
|
|
217
|
-
* not on offer.
|
|
327
|
+
* attribute to a judge is a floor nobody can tell apart from a moved one.
|
|
328
|
+
* 3. `runJudgedFloor` refuses to grade when the stored identity is not the one
|
|
329
|
+
* about to grade, naming both. It does not degrade in either direction:
|
|
330
|
+
* grading on the new judge judges against a floor nobody calibrated, and
|
|
331
|
+
* the old judge is not on offer.
|
|
218
332
|
*/
|
|
219
333
|
export const JUDGE_MODEL: "claude-haiku-4-5";
|
|
220
334
|
/**
|
package/types/kinds.d.ts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The judged stages of a close declaration, and whether it has any — the ONE
|
|
3
|
+
* spelling of "does this close ask a model to render anything?".
|
|
4
|
+
*
|
|
5
|
+
* The comment above `JUDGED_FLOOR_KIND` says five literals is how the readers
|
|
6
|
+
* come to disagree, and by PRD item 31.4 there were SIX open-coded
|
|
7
|
+
* `stages.filter(s => s.kind === JUDGED_FLOOR_KIND)` across the tree
|
|
8
|
+
* (`src/authorjob.js` twice, `src/cardauthor.js`, `src/declaredclose.js`,
|
|
9
|
+
* `scripts/run-author.mjs`, `scripts/author-readout.mjs`). 31.4 needed a
|
|
10
|
+
* seventh, in the runner, to decide whether a judge KEY is demanded — and a
|
|
11
|
+
* seventh spelling deciding a REFUSAL is the drift `scripts/run-u.mjs`'s own
|
|
12
|
+
* judge-provider comment warns about ("a second reading of the declaration
|
|
13
|
+
* that can drift from the one the runner actually executes"). So there is one
|
|
14
|
+
* reading now, and every caller shares it.
|
|
15
|
+
*
|
|
16
|
+
* Defensive on shape ON PURPOSE: callers pass raw specs read off disk and
|
|
17
|
+
* half-built drafts, not validated declarations. An absent/!object `closeDecl`
|
|
18
|
+
* or `stages` is "no judged stages", never a throw — the close VALIDATOR is
|
|
19
|
+
* what rejects a malformed declaration, and this predicate answering a
|
|
20
|
+
* question about one is not the place to re-litigate it.
|
|
21
|
+
* @param {any} closeDecl a close declaration (or anything, including undefined)
|
|
22
|
+
* @returns {any[]} the judged-floor stages, in declaration order
|
|
23
|
+
*/
|
|
24
|
+
export function judgedStages(closeDecl: any): any[];
|
|
25
|
+
/**
|
|
26
|
+
* Does this close declaration judge — i.e. will a judge model be CALLED?
|
|
27
|
+
* The question `scripts/run-u.mjs` asks before demanding a judge key (PRD item
|
|
28
|
+
* 31.4): a job that never judges must run on its own provider's key alone.
|
|
29
|
+
* @param {any} closeDecl
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export function closeJudges(closeDecl: any): boolean;
|
|
1
33
|
/**
|
|
2
34
|
* Does this run end at a review door? The operator's flag WINS in both
|
|
3
35
|
* directions and is never inferred: `true` opens it for any class, `false` shuts
|
|
@@ -531,14 +563,25 @@ export type Red = {
|
|
|
531
563
|
* runner — never authored, never defaulted, and absent on every ordinary run.
|
|
532
564
|
* `judgeLoop` is the PAID seam the judged stage runs its locate call through, and
|
|
533
565
|
* it is operator territory for the same reason the worker's provider is: this
|
|
534
|
-
* module owns no provider and never picks one
|
|
535
|
-
*
|
|
536
|
-
* model — the stage stops as a wiring gap, the same answer `runPlan` gives a
|
|
566
|
+
* module owns no provider and never picks one. Absent is not a fall-back to some
|
|
567
|
+
* other model — the stage stops as a wiring gap, the same answer `runPlan` gives a
|
|
537
568
|
* native job with no native factory.
|
|
569
|
+
* `judgeModel` is the seam's other half (PRD item 32.1): WHICH model that loop
|
|
570
|
+
* drives, resolved by the runner (`resolveJudge`, src/judged.js — the spec's signed
|
|
571
|
+
* `judge` override, else the job's own worker model) rather than pinned in this
|
|
572
|
+
* library. It is required whenever `judgeLoop` is, and for the same reason: a
|
|
573
|
+
* verdict whose grader cannot be named is a floor nobody can attribute, and the
|
|
574
|
+
* signed calibration record has nothing to compare against. The two travel
|
|
575
|
+
* together or the stage stops.
|
|
538
576
|
* `onJudgeCost` is the METER, and it is the only reason a judged stage can be
|
|
539
577
|
* funded honestly: this executor cannot reach the run's ledger, so every locate
|
|
540
578
|
* call's cost is reported OUT through it, once per call, on every route including
|
|
541
579
|
* the red ones — a paid call that leaves no meter record is F12 in a judge's coat.
|
|
580
|
+
* `callBounds` is F152/PRD 30.4's per-call TIME bound, read fresh before every
|
|
581
|
+
* locate attempt — the same derivation the run's own worker rounds carry
|
|
582
|
+
* (`callBounds()`, src/planrun.js). Absent is the honest unbounded default:
|
|
583
|
+
* an adopter or test that wires no clock through behaves exactly as before
|
|
584
|
+
* this field existed.
|
|
542
585
|
* `onStage` is a REPORTING seam and nothing else: the seed read spawns a real
|
|
543
586
|
* toolchain per stage (a suite is the slow one) and a whole read is one opaque
|
|
544
587
|
* await, so the shell gets told as each stage lands. It decides nothing, it is
|
|
@@ -561,6 +604,7 @@ export type Ctx = {
|
|
|
561
604
|
judgeLoop?: (o: {
|
|
562
605
|
system: string;
|
|
563
606
|
}) => any;
|
|
607
|
+
judgeModel?: string;
|
|
564
608
|
onJudgeCost?: (c: {
|
|
565
609
|
stage: string | null;
|
|
566
610
|
kind: string | null;
|
|
@@ -571,6 +615,10 @@ export type Ctx = {
|
|
|
571
615
|
costUsd: number | null;
|
|
572
616
|
unpricedRounds: number;
|
|
573
617
|
}) => void;
|
|
618
|
+
callBounds?: () => {
|
|
619
|
+
timeoutMs?: number;
|
|
620
|
+
deadlineMs?: number;
|
|
621
|
+
};
|
|
574
622
|
onStage?: (row: {
|
|
575
623
|
stage: string | null;
|
|
576
624
|
kind: string | null;
|
package/types/planrun.d.ts
CHANGED
|
@@ -196,8 +196,15 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
196
196
|
* `false` → the drafter has no tools, so a native session would report NO cost — return a
|
|
197
197
|
* metered claude-json TEXT provider (`--output-format json`, `parse:'claude-json'`) instead,
|
|
198
198
|
* so its spend is never invisible. The Loop path (`anthropic-api`) never touches this.
|
|
199
|
+
* @param {string|null} [opts.judgeModel] softgreen — WHICH model that judge provider drives
|
|
200
|
+
* (PRD item 32.1). Resolved by the CALLER (`resolveJudge`, src/judged.js: the spec's signed
|
|
201
|
+
* `judge` override, else the job's own worker model), never pinned in this library. It
|
|
202
|
+
* travels with `judgeProvider` or the judged stage stops as a wiring gap: a verdict whose
|
|
203
|
+
* grader cannot be named is a floor nobody can attribute.
|
|
199
204
|
* @param {any} [opts.judgeProvider] softgreen — the provider a JUDGED close stage runs its
|
|
200
|
-
* locate call through,
|
|
205
|
+
* locate call through, built by the CALLER from the RESOLVED judge identity (PRD item
|
|
206
|
+
* 32.1: `resolveJudge`, src/judged.js — the spec's signed `judge` override, else the job's
|
|
207
|
+
* own worker provider and model), never pinned in this library. Separate
|
|
201
208
|
* from `provider`/`providerFor` on purpose: the judge tier is not a step knob and never
|
|
202
209
|
* agent-selectable, and the worker's binding is not a legal stand-in for it. Absent is not
|
|
203
210
|
* a fall-back — a judged stage with no seam instrument-STOPS as a wiring gap, the same
|
|
@@ -410,7 +417,7 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
410
417
|
* 'branch-red' | 'cap-halt' | 'wall-halt' | 'provider-red' | 'interpreter-red' |
|
|
411
418
|
* 'step-stalled' | 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
412
419
|
*/
|
|
413
|
-
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, judgeProvider, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, closeDir, maxStepRounds, layerRoot, readShim, scout, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, priorSpentUsd, reviewDoor, doorRerun, resumable }: {
|
|
420
|
+
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, judgeProvider, judgeModel, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, closeDir, maxStepRounds, layerRoot, readShim, scout, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, priorSpentUsd, reviewDoor, doorRerun, resumable }: {
|
|
414
421
|
workdir: string;
|
|
415
422
|
provider: any;
|
|
416
423
|
nativeProvider?: ((o: {
|
|
@@ -419,6 +426,7 @@ export function runPlan(job: any, { workdir, provider, nativeProvider, providerF
|
|
|
419
426
|
maxTurns: number;
|
|
420
427
|
hasTools: boolean;
|
|
421
428
|
}) => any) | undefined;
|
|
429
|
+
judgeModel?: string | null | undefined;
|
|
422
430
|
judgeProvider?: any;
|
|
423
431
|
emit: (type: string, data?: object) => object;
|
|
424
432
|
remainingUsd: () => number;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Look up a provider's table entry. Throws a NAMED error on an unrecognized
|
|
3
|
+
* provider — never a silent default (the `resolveRates`-style-substring-
|
|
4
|
+
* match lesson: a forward hazard even at zero observed rounds, MEMORY.md).
|
|
5
|
+
* `src/job.js`'s `PROVIDERS` menu is the one place a spec's `provider`
|
|
6
|
+
* field is validated; this is the runtime construction seam it feeds.
|
|
7
|
+
* @param {string} providerName
|
|
8
|
+
* @returns {ProviderTableEntry}
|
|
9
|
+
*/
|
|
10
|
+
export function resolveProvider(providerName: string): ProviderTableEntry;
|
|
11
|
+
/**
|
|
12
|
+
* Construct ONE provider instance for `providerName`/`model`, applying
|
|
13
|
+
* `exposeErrorBody: true` (F153 — every constructed provider, unconditionally)
|
|
14
|
+
* and the model's own request-key gating (`paramsFor`). `baseUrl` (PRD item
|
|
15
|
+
* 28, ruling (d), 2026-09-09: admitted in v1) is forwarded only when given —
|
|
16
|
+
* every provider constructor here defaults it on its own when absent.
|
|
17
|
+
* @param {string} providerName
|
|
18
|
+
* @param {{apiKey?: string, model?: string, baseUrl?: string}} [options]
|
|
19
|
+
*/
|
|
20
|
+
export function makeProvider(providerName: string, { apiKey, model, baseUrl }?: {
|
|
21
|
+
apiKey?: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
baseUrl?: string;
|
|
24
|
+
}): any;
|
|
25
|
+
/**
|
|
26
|
+
* Build the `{provider, providerFor, judgeProvider}` triple both runners
|
|
27
|
+
* need (`src/cli.js`'s `buildProviders`, `scripts/run-u.mjs`'s top-level
|
|
28
|
+
* wiring) — ONE seam instead of two copies of the same construction and
|
|
29
|
+
* tier-memoization logic. `model`/`tierModels` are already-RESOLVED inputs
|
|
30
|
+
* (the caller runs `resolveWorkerModel` itself, exactly as both runners did
|
|
31
|
+
* before this factory existed — that decision stays where each runner's own
|
|
32
|
+
* `--model` flag/spec precedence lives, not duplicated in here).
|
|
33
|
+
*
|
|
34
|
+
* THE JUDGE IS NO LONGER PINNED TO ANTHROPIC (PRD item 32.2, hamr 2026-09-10:
|
|
35
|
+
* *"what i care about is that judge becomes llm agnostic and not set to one
|
|
36
|
+
* model or provider"*). It is constructed through this same factory, from a
|
|
37
|
+
* `judgeProviderName`/`judgeModel` pair the CALLER resolved (`resolveJudge`,
|
|
38
|
+
* src/judged.js — the spec's signed `judge` override, else the job's own worker
|
|
39
|
+
* provider and model). Item 28's pin, and item 28 part (2)'s deferral of a
|
|
40
|
+
* signed `judge:{provider,model}` field, both close here.
|
|
41
|
+
*
|
|
42
|
+
* `judgeApiKey` stays a SEPARATE argument rather than being derived: the judge
|
|
43
|
+
* may legitimately be a different provider from the worker, and reading its key
|
|
44
|
+
* for it would put a second env-var reader in a module whose whole job is to
|
|
45
|
+
* have exactly one. The caller reads the resolved judge provider's own `envKey`
|
|
46
|
+
* and hands the key in — the same contract the worker key already has here.
|
|
47
|
+
* @param {object} args
|
|
48
|
+
* @param {string} args.providerName spec.provider (or the anthropic-api default)
|
|
49
|
+
* @param {string|undefined} args.apiKey the WORKER's key, read from the provider's own `envKey`
|
|
50
|
+
* @param {string} args.model the already-resolved worker model id
|
|
51
|
+
* @param {Readonly<Record<string, string>>} args.tierModels the already-resolved tier -> model map (spec override folded in by the caller)
|
|
52
|
+
* @param {string|undefined} [args.baseUrl] spec.baseUrl, if any
|
|
53
|
+
* @param {string|undefined} args.judgeApiKey the judge's own key, read by the caller from the RESOLVED judge provider's `envKey`
|
|
54
|
+
* @param {string} args.judgeModel the resolved judge model id
|
|
55
|
+
* @param {string} [args.judgeProviderName] the resolved judge provider name; defaults to `providerName` (the job's own worker provider), which is `resolveJudge`'s own default
|
|
56
|
+
* @param {string|undefined} [args.judgeBaseUrl] the judge provider's endpoint, when it takes one
|
|
57
|
+
*/
|
|
58
|
+
export function buildRunnerProviders({ providerName, apiKey, model, tierModels, baseUrl, judgeApiKey, judgeModel, judgeProviderName, judgeBaseUrl, }: {
|
|
59
|
+
providerName: string;
|
|
60
|
+
apiKey: string | undefined;
|
|
61
|
+
model: string;
|
|
62
|
+
tierModels: Readonly<Record<string, string>>;
|
|
63
|
+
baseUrl?: string | undefined;
|
|
64
|
+
judgeApiKey: string | undefined;
|
|
65
|
+
judgeModel: string;
|
|
66
|
+
judgeProviderName?: string | undefined;
|
|
67
|
+
judgeBaseUrl?: string | undefined;
|
|
68
|
+
}): {
|
|
69
|
+
provider: any;
|
|
70
|
+
providerFor: (tier: string) => any;
|
|
71
|
+
judgeProvider: any;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The launch-time warning lines for an ADMITTED-PENDING-PROBE provider, or
|
|
75
|
+
* `null` when the provider has paid for its own end-to-end probe (and for an
|
|
76
|
+
* off-table name — an unknown provider is `resolveProvider`'s named throw to
|
|
77
|
+
* report, never this function's warning to soften).
|
|
78
|
+
*
|
|
79
|
+
* This lives here, next to `PROBE_STATUS`, rather than inline in the runner,
|
|
80
|
+
* for one reason: inline it was UNTESTABLE. `scripts/run-u.mjs` reaches this
|
|
81
|
+
* point only with a real job row (a machine-local patient path) and a real
|
|
82
|
+
* signed spec, so nothing in the suite could reach the branch, and a warning
|
|
83
|
+
* nothing executes drifts exactly the way the green-only prose did (item 31.2).
|
|
84
|
+
*
|
|
85
|
+
* It never REFUSES, and it never returns a shape a caller can mistake for a
|
|
86
|
+
* refusal: hamr admitted `gemini-api` to the menu, and a probe table that
|
|
87
|
+
* quietly withheld it would be a second ruling nobody made.
|
|
88
|
+
* @param {string} providerName
|
|
89
|
+
* @returns {string[]|null} lines to print, in order, or null when there is nothing to say
|
|
90
|
+
*/
|
|
91
|
+
export function probeWarningLines(providerName: string): string[] | null;
|
|
92
|
+
/**
|
|
93
|
+
* Today's anthropic-api tier table — EXACTLY the `DEFAULT_TIER_MODELS` both
|
|
94
|
+
* runners hardcoded before this factory existed. Any change to these two
|
|
95
|
+
* values is a change to shipped anthropic-api behaviour, not a refactor.
|
|
96
|
+
*/
|
|
97
|
+
export const ANTHROPIC_TIER_MODELS: Readonly<{
|
|
98
|
+
sonnet: "claude-sonnet-5";
|
|
99
|
+
haiku: "claude-haiku-4-5-20251001";
|
|
100
|
+
}>;
|
|
101
|
+
/**
|
|
102
|
+
* DeepSeek (F149/F150) is a SINGLE model, not a tiered family — hamr's
|
|
103
|
+
* ruling above: one secondary provider, not a menu. Both tiers map to the
|
|
104
|
+
* same model id ON PURPOSE: `resolveWorkerModel`/a runner's `providerFor
|
|
105
|
+
* (tier)` only ever LOOK UP a tier's model id (src/job.js:818-827,
|
|
106
|
+
* scripts/run-u.mjs's `providerFor`) — neither assumes the tiers name
|
|
107
|
+
* different models — so repeating the one id is the honest representation
|
|
108
|
+
* of a single-model provider, not a second model masquerading as `haiku`.
|
|
109
|
+
* If DeepSeek (or a future openai-api entrant) ever ships a genuinely
|
|
110
|
+
* cheaper tier model, this is where it would earn its own `haiku` id.
|
|
111
|
+
*/
|
|
112
|
+
export const OPENAI_TIER_MODELS: Readonly<{
|
|
113
|
+
sonnet: "deepseek-chat";
|
|
114
|
+
haiku: "deepseek-chat";
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* Gemini (PRD item 31.3, hamr 2026-09-09: "anthropic, openai, gemini drop
|
|
118
|
+
* ollama for now"). Two real tiers, unlike DeepSeek's single model: `flash` is
|
|
119
|
+
* the cheap tier by design, so `haiku` maps to it honestly rather than
|
|
120
|
+
* repeating one id.
|
|
121
|
+
*
|
|
122
|
+
* ADMITTED-PENDING-PROBE. The probe rule stands (PRD item 28 ruling (d),
|
|
123
|
+
* 2026-09-09): no endpoint is in the menu without its own clean paid probe,
|
|
124
|
+
* and `gemini-api` has ZERO runs. `anthropic-api` is the original (~167
|
|
125
|
+
* archived runs) and `openai-api` was probed green through the shipped runner
|
|
126
|
+
* (run mtu12vks, $1.64/$4, F157); gemini owes that fire and has not paid it.
|
|
127
|
+
* `PROBE_STATUS` below is the machine-readable form of that debt — nothing in
|
|
128
|
+
* here silently pretends the provider is proven.
|
|
129
|
+
*/
|
|
130
|
+
export const GEMINI_TIER_MODELS: Readonly<{
|
|
131
|
+
sonnet: "gemini-2.5-pro";
|
|
132
|
+
haiku: "gemini-2.5-flash";
|
|
133
|
+
}>;
|
|
134
|
+
/**
|
|
135
|
+
* Which admitted providers have paid for their own end-to-end probe, and which
|
|
136
|
+
* have not. Read by the runner to print a loud marker; never read to REFUSE —
|
|
137
|
+
* hamr admitted gemini to the menu, and a table that quietly withheld it would
|
|
138
|
+
* be a second, invisible ruling. An unprobed provider runs, and says so.
|
|
139
|
+
* @type {Readonly<Record<string, {probed: boolean, evidence: string}>>}
|
|
140
|
+
*/
|
|
141
|
+
export const PROBE_STATUS: Readonly<Record<string, {
|
|
142
|
+
probed: boolean;
|
|
143
|
+
evidence: string;
|
|
144
|
+
}>>;
|
|
145
|
+
export type ProviderTableEntry = {
|
|
146
|
+
/**
|
|
147
|
+
* the bare-agent provider class
|
|
148
|
+
*/
|
|
149
|
+
ctor: new (options: any) => any;
|
|
150
|
+
/**
|
|
151
|
+
* the environment variable this provider reads its key from
|
|
152
|
+
*/
|
|
153
|
+
envKey: string;
|
|
154
|
+
/**
|
|
155
|
+
* tier name -> model id
|
|
156
|
+
*/
|
|
157
|
+
tiers: Readonly<Record<string, string>>;
|
|
158
|
+
/**
|
|
159
|
+
* the CONSTRUCTOR OPTION NAME this provider reads its endpoint from — NOT assumed to be `baseUrl` (see below)
|
|
160
|
+
*/
|
|
161
|
+
endpointKey: string;
|
|
162
|
+
/**
|
|
163
|
+
* per-model request-key/param gating, applied on TOP of {exposeErrorBody:true, apiKey, model, <endpointKey>?}
|
|
164
|
+
*/
|
|
165
|
+
paramsFor: (model: string | undefined) => Record<string, any>;
|
|
166
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is `err` an HTTP 429 (rate-limited) response? True ONLY for an explicit
|
|
3
|
+
* status of 429 on the error itself. Nothing else qualifies — not message
|
|
4
|
+
* text (a message merely containing "429" is not this), not `retryable`,
|
|
5
|
+
* not any other status. Symmetric with `isTransportFailure`'s own status
|
|
6
|
+
* check (src/transport.js), just reading the opposite branch of it.
|
|
7
|
+
* @param {any} err
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
*/
|
|
10
|
+
export function isRateLimited(err: any): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The vendor's RAW stated wait, in milliseconds, parsed straight from the
|
|
13
|
+
* error message — no default, no margin, no cap. `null` when nothing in the
|
|
14
|
+
* message matches a known shape. Exported separately from `rateLimitWaitMs`
|
|
15
|
+
* so a caller that wants to report the vendor's own number on the spine
|
|
16
|
+
* (`statedMs`) never has to re-derive it from the margin-adjusted figure.
|
|
17
|
+
*
|
|
18
|
+
* bare-agent does not expose the vendor's `retry-after` /
|
|
19
|
+
* `x-ratelimit-reset-*` response headers on the thrown error (BA-26) — the
|
|
20
|
+
* delay exists only in the vendor's English message text, so this parses
|
|
21
|
+
* that text. Verified real shape (OpenAI, run `8ev2sdkn`, 2026-09-08):
|
|
22
|
+
* "Please try again in 11.996s." This also supports "try again in 1.5
|
|
23
|
+
* seconds", "try again in 20ms", "retry after 30s", and "retry after 30
|
|
24
|
+
* seconds" — case-insensitive.
|
|
25
|
+
* @param {any} err
|
|
26
|
+
* @returns {number|null}
|
|
27
|
+
*/
|
|
28
|
+
export function statedWaitMs(err: any): number | null;
|
|
29
|
+
/**
|
|
30
|
+
* How long to wait before retrying a 429, in milliseconds — or `null`
|
|
31
|
+
* meaning "do not retry at all" (either the parsed wait exceeds
|
|
32
|
+
* `RATE_LIMIT_MAX_WAIT_MS`, in which case waiting that long is the
|
|
33
|
+
* operator's decision, not ours).
|
|
34
|
+
*
|
|
35
|
+
* A parsed value gets `PARSED_DELAY_MARGIN_MS` added (the vendor's stated
|
|
36
|
+
* number is the earliest moment its window resets, not a safe one to fire
|
|
37
|
+
* on), capped so the margin itself can never push a parsed value over
|
|
38
|
+
* `RATE_LIMIT_MAX_WAIT_MS`. When nothing parses, `RATE_LIMIT_DEFAULT_WAIT_MS`
|
|
39
|
+
* is returned as-is, with no margin added (there is nothing to add margin
|
|
40
|
+
* to — it is already a conservative guess, not an earliest-moment reading).
|
|
41
|
+
* @param {any} err
|
|
42
|
+
* @returns {number|null}
|
|
43
|
+
*/
|
|
44
|
+
export function rateLimitWaitMs(err: any): number | null;
|
|
45
|
+
/** The fixed retry budget: ONE extra attempt after a 429. Never read from a
|
|
46
|
+
* job spec or CLI flag — raising it is arbiter territory, mirroring
|
|
47
|
+
* transport.js's TRANSPORT_RETRIES exactly (tighten-only doctrine). */
|
|
48
|
+
export const RATE_LIMIT_RETRIES: 1;
|
|
49
|
+
/** bare-agent's `Retry.call` (if ever used) counts ATTEMPTS, not retries;
|
|
50
|
+
* this module's own hand-rolled ladder (src/planrun.js) does the same for
|
|
51
|
+
* symmetry with TRANSPORT_MAX_ATTEMPTS. */
|
|
52
|
+
export const RATE_LIMIT_MAX_ATTEMPTS: number;
|
|
53
|
+
/** The hard cap on how long we will ever wait for a vendor-stated 429 delay.
|
|
54
|
+
* A vendor asking for longer than this is not honoured — we do not retry at
|
|
55
|
+
* all in that case. Waiting that long is the operator's decision, not ours
|
|
56
|
+
* (arbiter territory: nothing here escalates the wait past what hamr set). */
|
|
57
|
+
export const RATE_LIMIT_MAX_WAIT_MS: 60000;
|
|
58
|
+
/** Used only when the vendor's message carries no parseable delay at all. */
|
|
59
|
+
export const RATE_LIMIT_DEFAULT_WAIT_MS: 5000;
|
package/types/run.d.ts
CHANGED
|
@@ -34,9 +34,14 @@
|
|
|
34
34
|
* metered claude-json text provider for the toolless drafter); ignored on every Loop-driven provider
|
|
35
35
|
* @param {(type: string, data?: object) => object} opts.emit spine emitter
|
|
36
36
|
* @param {(tier: string) => any} [opts.providerFor] P: per-step model-tier provider factory (forwarded to the plan flow)
|
|
37
|
+
* @param {string|null} [opts.judgeModel] SOFTGREEN — WHICH model the judge provider drives
|
|
38
|
+
* (PRD item 32.1), resolved by the CALLER (`resolveJudge`, src/judged.js) and passed
|
|
39
|
+
* through untouched. Travels with `judgeProvider`; absent, a judged stage stops as a
|
|
40
|
+
* wiring gap rather than grading under an identity nobody named.
|
|
37
41
|
* @param {any} [opts.judgeProvider] SOFTGREEN — the provider a JUDGED close stage runs its
|
|
38
|
-
* locate call through,
|
|
39
|
-
*
|
|
42
|
+
* locate call through, built by the CALLER from the RESOLVED judge identity (PRD item
|
|
43
|
+
* 32.1: `resolveJudge`/`resolveJobJudge`, src/judged.js — the spec's signed `judge`
|
|
44
|
+
* override, else the job's own worker provider and model), never pinned. Forwarded to the plan
|
|
40
45
|
* flow. It is its own seam and not `provider`/`providerFor`, because the judge tier is
|
|
41
46
|
* never a step knob and never agent-selectable; absent, a judged stage instrument-stops as
|
|
42
47
|
* a wiring gap rather than grading on whatever binding happened to be at hand. Its spend
|
|
@@ -167,8 +172,16 @@
|
|
|
167
172
|
* 'close-red' | 'close-unsupported' | 'recipe-stale' | 'branch-red' | 'pricing-red' | 'provider-red' |
|
|
168
173
|
* 'interpreter-red' | 'cap-halt' | 'wall-halt' | 'step-stalled' |
|
|
169
174
|
* 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
175
|
+
* NOTE: `job-end` can ALSO land with outcome 'runner-drained' (F140/PRD item
|
|
176
|
+
* 28(c)) — the `beforeExit` backstop's own terminal, emitted from OUTSIDE this
|
|
177
|
+
* function's normal control flow when the process drains with no `job-end` at
|
|
178
|
+
* all (a provider promise that never settled). It never appears as this
|
|
179
|
+
* function's own RETURN value (nothing is left to receive it), only as the
|
|
180
|
+
* spine's terminal record. Non-zero exit, `spendComplete:false` always, and
|
|
181
|
+
* deliberately NOT in the resumable/checkpoint set (`src/reuse.js`) — an
|
|
182
|
+
* unknown in-flight state is not a known-safe resume point.
|
|
170
183
|
*/
|
|
171
|
-
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, closeDir, layerRoot, readShim, scout, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun, resumable }: {
|
|
184
|
+
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider, judgeModel, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, closeDir, layerRoot, readShim, scout, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun, resumable }: {
|
|
172
185
|
approvals: unknown;
|
|
173
186
|
workdir: string;
|
|
174
187
|
provider: any;
|
|
@@ -180,6 +193,7 @@ export function runJob(rawSpec: object | string, { approvals, workdir, provider,
|
|
|
180
193
|
}) => any) | undefined;
|
|
181
194
|
emit: (type: string, data?: object) => object;
|
|
182
195
|
providerFor?: ((tier: string) => any) | undefined;
|
|
196
|
+
judgeModel?: string | null | undefined;
|
|
183
197
|
judgeProvider?: any;
|
|
184
198
|
capRuns?: number | undefined;
|
|
185
199
|
strikeLimit?: number | undefined;
|
package/types/transport.d.ts
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
* Is `err` a transport-class failure — the request never produced an HTTP
|
|
3
3
|
* response? True for: a TLS fault mid-record ("bad record mac" and kin), a
|
|
4
4
|
* reset/broken/timed-out socket (ECONNRESET, EPIPE, ETIMEDOUT, ECONNREFUSED,
|
|
5
|
-
* ENETUNREACH — by code on the error itself or on `err.cause`),
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* ENETUNREACH — by code on the error itself or on `err.cause`), `fetch
|
|
6
|
+
* failed` wrapping a network `cause`, and — as of bare-agent 0.42.0 (BA-25)
|
|
7
|
+
* — a `ProviderError` whose `err.context.bound === 'transport'`: the
|
|
8
|
+
* response stream ended (`'aborted'`/`'error'`/premature `'close'`) after
|
|
9
|
+
* headers but before the body completed, which bare-agent itself rejects as
|
|
10
|
+
* retryable with no HTTP status. False for anything carrying an HTTP status
|
|
11
|
+
* (`err.status`/`err.statusCode`, 4xx/5xx/429) or an explicit
|
|
8
12
|
* `err.retryable === false` — those are provider RESPONSES, not transport
|
|
9
|
-
* casualties, and bare-agent's own policy governs them unchanged
|
|
13
|
+
* casualties, and bare-agent's own policy governs them unchanged; both
|
|
14
|
+
* guards run BEFORE the `context.bound` check, so a status or an explicit
|
|
15
|
+
* `retryable:false` wins even if `bound` says 'transport'.
|
|
10
16
|
* @param {any} err
|
|
11
17
|
* @returns {boolean}
|
|
12
18
|
*/
|