bareloop 0.39.0 → 0.41.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 +60 -0
- package/bareloop.context.md +137 -112
- package/package.json +2 -2
- package/src/authorflow.js +333 -58
- package/src/authoring.js +65 -2
- package/src/authorjob.js +57 -9
- package/src/authorreadout.js +50 -2
- package/src/authorrun.js +30 -27
- package/src/authorscout.js +9 -6
- package/src/bridges.js +1 -1
- package/src/bundle.js +7 -4
- package/src/bundlerun.js +4 -1
- package/src/calibrate.js +1 -1
- package/src/cardauthor.js +4 -1
- package/src/cli.js +1 -1
- package/src/config.js +129 -29
- package/src/declaredclose.js +4 -3
- package/src/draftspend.js +6 -1
- package/src/index.js +2 -4
- package/src/interviewrun.js +73 -52
- package/src/job.js +50 -11
- package/src/jobblock.js +140 -0
- package/src/judged.js +12 -44
- package/src/keysfile.js +15 -7
- package/src/kinds.js +2 -2
- package/src/ledger.js +1 -1
- package/src/modellist.js +84 -0
- package/src/monthly.js +23 -43
- package/src/panel/authorroutes.js +34 -19
- package/src/panel/authorsession.js +187 -72
- package/src/panel/index.html +699 -215
- package/src/panel/jobplan.js +107 -0
- package/src/panel/runroutes.js +3 -0
- package/src/panel/server.js +102 -28
- package/src/panel/settingsroutes.js +232 -173
- package/src/planrun.js +6 -6
- package/src/promptregisters.js +1 -1
- package/src/providerrows.js +226 -141
- package/src/providers.js +58 -250
- package/src/providershapes.js +18 -0
- package/src/replay.js +1 -1
- package/src/reuse.js +1 -1
- package/src/root.js +1 -1
- package/src/run.js +3 -3
- package/src/selection.js +1 -1
- package/src/source.js +64 -1
- package/src/text.js +13 -0
- package/src/thinking.js +130 -0
- package/src/transport.js +1 -1
- package/src/userrun.js +53 -76
- package/types/authorflow.d.ts +258 -39
- package/types/authoring.d.ts +7 -1
- package/types/authorjob.d.ts +35 -3
- package/types/authorreadout.d.ts +17 -1
- package/types/authorscout.d.ts +5 -3
- package/types/config.d.ts +23 -6
- package/types/declaredclose.d.ts +4 -1
- package/types/draftspend.d.ts +8 -2
- package/types/index.d.ts +1 -1
- package/types/job.d.ts +6 -6
- package/types/jobblock.d.ts +102 -0
- package/types/judged.d.ts +5 -36
- package/types/keysfile.d.ts +15 -4
- package/types/modellist.d.ts +50 -0
- package/types/monthly.d.ts +4 -3
- package/types/panel/authorsession.d.ts +44 -15
- package/types/panel/jobplan.d.ts +58 -0
- package/types/panel/server.d.ts +34 -4
- package/types/planrun.d.ts +1 -1
- package/types/providerrows.d.ts +192 -99
- package/types/providers.d.ts +35 -116
- package/types/providershapes.d.ts +10 -0
- package/types/run.d.ts +1 -1
- package/types/source.d.ts +26 -0
- package/types/thinking.d.ts +90 -0
- package/types/userrun.d.ts +6 -1
package/types/authorjob.d.ts
CHANGED
|
@@ -79,26 +79,38 @@ export function refuseLockedKind(kind: string): Refusal;
|
|
|
79
79
|
* one-genre-at-a-time law is untouched.
|
|
80
80
|
*
|
|
81
81
|
* @param {{answers: Record<string|number, any>, repoPath?: string|null, lang: string,
|
|
82
|
+
* jobLines?: {n: number, text: string}[]|null, inputs?: {n: number, label: string, value: string}[]|null,
|
|
82
83
|
* verdictType?: string|null,
|
|
83
84
|
* questions?: Record<string|number, string>|null, generate?: Function, provider?: any,
|
|
84
85
|
* seedRef?: string|null, scout?: any, listing?: any, ceilingUsd?: number|null, judgeModel?: string|null,
|
|
85
|
-
* rates?: {in: number, out: number}|null,
|
|
86
|
+
* rates?: {in: number, out: number}|null, draftThinking?: 'on'|'off',
|
|
86
87
|
* onPhase?: (phase: string, data?: any) => void,
|
|
87
|
-
* onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number}) => void,
|
|
88
|
+
* onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number, thinkingStatus?: string}) => void,
|
|
88
89
|
* seedFn?: Function, scoutFn?: Function, listingFn?: Function,
|
|
89
90
|
* authorFn?: Function, authorOpts?: object, writeScope?: string[]|null,
|
|
90
91
|
* signerFix?: Function|any, proposeFn?: Function, compileOpts?: object,
|
|
91
92
|
* ask?: ((step: {kind: string, [k: string]: any}) => Promise<string|null>)|null,
|
|
93
|
+
* answerQuestions?: ((o: {questions: {line: number, question: string}[], dropped: {reason: string, raw: any}[], confirmed: any}) =>
|
|
94
|
+
* Promise<{jobLines: {n: number, text: string, rule?: string}[], answers: Record<string|number, any>}|null>)|null,
|
|
92
95
|
* confirmGenerate?: Function|null, isRepo?: boolean,
|
|
93
96
|
* langResult?: {kind: string, candidates?: string[], [k: string]: any}|null}} o
|
|
94
97
|
* @returns {Promise<{ok: boolean, refusal: Refusal|null, verdictType: string|null,
|
|
95
98
|
* closeDecl: any, seedRef: string|null, authoring: any, judged: any, reds: Red[],
|
|
96
99
|
* stop: string|null, cost: any, interview: any, confirmed: any}>}
|
|
97
100
|
*/
|
|
98
|
-
export function authorCloseForJob({ answers, repoPath, lang, verdictType, questions, generate, provider, seedRef, scout, listing, ceilingUsd, rates, writeScope, judgeModel, onPhase, onCall, seedFn, scoutFn, listingFn, authorFn, authorOpts, signerFix, proposeFn, compileOpts, ask, confirmGenerate, isRepo, langResult, }: {
|
|
101
|
+
export function authorCloseForJob({ answers, repoPath, lang, verdictType, questions, jobLines, inputs, generate, provider, seedRef, scout, listing, ceilingUsd, rates, draftThinking, writeScope, judgeModel, onPhase, onCall, seedFn, scoutFn, listingFn, authorFn, authorOpts, signerFix, proposeFn, compileOpts, ask, confirmGenerate, isRepo, langResult, answerQuestions, }: {
|
|
99
102
|
answers: Record<string | number, any>;
|
|
100
103
|
repoPath?: string | null;
|
|
101
104
|
lang: string;
|
|
105
|
+
jobLines?: {
|
|
106
|
+
n: number;
|
|
107
|
+
text: string;
|
|
108
|
+
}[] | null;
|
|
109
|
+
inputs?: {
|
|
110
|
+
n: number;
|
|
111
|
+
label: string;
|
|
112
|
+
value: string;
|
|
113
|
+
}[] | null;
|
|
102
114
|
verdictType?: string | null;
|
|
103
115
|
questions?: Record<string | number, string> | null;
|
|
104
116
|
generate?: Function;
|
|
@@ -112,11 +124,13 @@ export function authorCloseForJob({ answers, repoPath, lang, verdictType, questi
|
|
|
112
124
|
in: number;
|
|
113
125
|
out: number;
|
|
114
126
|
} | null;
|
|
127
|
+
draftThinking?: "on" | "off";
|
|
115
128
|
onPhase?: (phase: string, data?: any) => void;
|
|
116
129
|
onCall?: (call: {
|
|
117
130
|
label: string;
|
|
118
131
|
costUsd: number | null;
|
|
119
132
|
unpricedRounds: number;
|
|
133
|
+
thinkingStatus?: string;
|
|
120
134
|
}) => void;
|
|
121
135
|
seedFn?: Function;
|
|
122
136
|
scoutFn?: Function;
|
|
@@ -131,6 +145,24 @@ export function authorCloseForJob({ answers, repoPath, lang, verdictType, questi
|
|
|
131
145
|
kind: string;
|
|
132
146
|
[k: string]: any;
|
|
133
147
|
}) => Promise<string | null>) | null;
|
|
148
|
+
answerQuestions?: ((o: {
|
|
149
|
+
questions: {
|
|
150
|
+
line: number;
|
|
151
|
+
question: string;
|
|
152
|
+
}[];
|
|
153
|
+
dropped: {
|
|
154
|
+
reason: string;
|
|
155
|
+
raw: any;
|
|
156
|
+
}[];
|
|
157
|
+
confirmed: any;
|
|
158
|
+
}) => Promise<{
|
|
159
|
+
jobLines: {
|
|
160
|
+
n: number;
|
|
161
|
+
text: string;
|
|
162
|
+
rule?: string;
|
|
163
|
+
}[];
|
|
164
|
+
answers: Record<string | number, any>;
|
|
165
|
+
} | null>) | null;
|
|
134
166
|
confirmGenerate?: Function | null;
|
|
135
167
|
isRepo?: boolean;
|
|
136
168
|
langResult?: {
|
package/types/authorreadout.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export function declarationLines({ goal, closeDecl }: {
|
|
|
12
12
|
* F176'S FALLBACK, SAID OUT LOUD — the revise ladder kept the NEWEST SOUND
|
|
13
13
|
* declaration rather than the last one it happened to try, because "kept the
|
|
14
14
|
* last accepted revision" is not the same claim as "kept the best revision"
|
|
15
|
-
* (docs/
|
|
15
|
+
* (docs/wiki/FINDINGS.md F176). Absent on every run where the fallback never
|
|
16
16
|
* fired (the overwhelming majority), which is why this returns an EMPTY list
|
|
17
17
|
* rather than a "no fallback" line — a green close has nothing to say here and
|
|
18
18
|
* printing it every run would be noise, not information.
|
|
@@ -216,6 +216,22 @@ export function proposalStopText({ stop, reds, cases, spend, source }: {
|
|
|
216
216
|
} | null;
|
|
217
217
|
source?: "proposal" | "signer";
|
|
218
218
|
}): string;
|
|
219
|
+
/**
|
|
220
|
+
* @param {{stop: string, reds?: PlainRed[]|null, refusal?: {detail?: string}|null,
|
|
221
|
+
* spend?: {knownUsd?: number|null, spendComplete?: boolean|null}|null}} o
|
|
222
|
+
* @returns {string}
|
|
223
|
+
*/
|
|
224
|
+
export function draftStopText({ stop, reds, refusal, spend }: {
|
|
225
|
+
stop: string;
|
|
226
|
+
reds?: PlainRed[] | null;
|
|
227
|
+
refusal?: {
|
|
228
|
+
detail?: string;
|
|
229
|
+
} | null;
|
|
230
|
+
spend?: {
|
|
231
|
+
knownUsd?: number | null;
|
|
232
|
+
spendComplete?: boolean | null;
|
|
233
|
+
} | null;
|
|
234
|
+
}): string;
|
|
219
235
|
/**
|
|
220
236
|
* Plain sentences for the reds of a refused signing, one or more per red. Card and practice-case reds reuse the
|
|
221
237
|
* proposal table; an unknown code is a generic sentence that quotes the code.
|
package/types/authorscout.d.ts
CHANGED
|
@@ -92,15 +92,15 @@ export function defaultSurveyor({ workdir, granted, auditPath, ctx }: {
|
|
|
92
92
|
* @param {{workdir: string, provider?: any,
|
|
93
93
|
* rounds?: number, minBytes?: number, blobMax?: number, maxTokens?: number, ctx?: boolean,
|
|
94
94
|
* attempts?: number, ceilingUsd?: number|null, callTimeoutMs?: number,
|
|
95
|
-
* onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number}) => void,
|
|
95
|
+
* onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number, thinkingStatus?: string}) => void,
|
|
96
96
|
* createLoop?: (o: {system: string, policy: any, onLlmResult: any, provider: any, rates?: {in: number, out: number}}) => any,
|
|
97
|
-
* rates?: {in: number, out: number}|null,
|
|
97
|
+
* rates?: {in: number, out: number}|null, callOptions?: Record<string, any>,
|
|
98
98
|
* createSurveyor?: (o: {workdir: string, granted: readonly string[], ctx: boolean}) => Promise<any>}} o
|
|
99
99
|
* @returns {Promise<Survey & {raw: string, raws: ReturnType<typeof scrubRaw>[],
|
|
100
100
|
* calls: {label: string, costUsd: number|null, unpricedRounds: number}[],
|
|
101
101
|
* budgetStop: 'cap-halt'|'pricing-red'|null}>}
|
|
102
102
|
*/
|
|
103
|
-
export function runAuthorScout({ workdir, provider, rounds, minBytes, blobMax, maxTokens, ctx, attempts, ceilingUsd, callTimeoutMs, onCall, createLoop, rates, createSurveyor, }: {
|
|
103
|
+
export function runAuthorScout({ workdir, provider, rounds, minBytes, blobMax, maxTokens, ctx, attempts, ceilingUsd, callTimeoutMs, onCall, createLoop, rates, callOptions, createSurveyor, }: {
|
|
104
104
|
workdir: string;
|
|
105
105
|
provider?: any;
|
|
106
106
|
rounds?: number;
|
|
@@ -115,6 +115,7 @@ export function runAuthorScout({ workdir, provider, rounds, minBytes, blobMax, m
|
|
|
115
115
|
label: string;
|
|
116
116
|
costUsd: number | null;
|
|
117
117
|
unpricedRounds: number;
|
|
118
|
+
thinkingStatus?: string;
|
|
118
119
|
}) => void;
|
|
119
120
|
createLoop?: (o: {
|
|
120
121
|
system: string;
|
|
@@ -130,6 +131,7 @@ export function runAuthorScout({ workdir, provider, rounds, minBytes, blobMax, m
|
|
|
130
131
|
in: number;
|
|
131
132
|
out: number;
|
|
132
133
|
} | null;
|
|
134
|
+
callOptions?: Record<string, any>;
|
|
133
135
|
createSurveyor?: (o: {
|
|
134
136
|
workdir: string;
|
|
135
137
|
granted: readonly string[];
|
package/types/config.d.ts
CHANGED
|
@@ -16,15 +16,31 @@ export function configPath(home?: string): string;
|
|
|
16
16
|
export function readConfig(opts?: {
|
|
17
17
|
home?: string;
|
|
18
18
|
}): ConfigRead;
|
|
19
|
+
/**
|
|
20
|
+
* One key-row field's value problem in plain words, or null when fine.
|
|
21
|
+
* @param {string} field `model` | `shape` | `baseUrl` | `legacyMaxTokens`
|
|
22
|
+
* @param {unknown} v
|
|
23
|
+
* @returns {string|null}
|
|
24
|
+
*/
|
|
25
|
+
export function providerFieldProblem(field: string, v: unknown): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* THE one rule for a row's model lines, used by config validation and the Settings routes. A price
|
|
28
|
+
* is a PAIR (`inPerM` and `outPerM`, each a finite number >= 0 — 0 / 0 typed is a chosen price) or
|
|
29
|
+
* neither (null / absent). A ticked line (`use`) needs both. Plain words, or null.
|
|
30
|
+
* @param {unknown} list
|
|
31
|
+
* @returns {string|null}
|
|
32
|
+
*/
|
|
33
|
+
export function modelsProblem(list: unknown): string | null;
|
|
19
34
|
/**
|
|
20
35
|
* Apply a patch and write. `null` deletes a field. Top-level fields shallow-merge;
|
|
21
|
-
* `keys` merges per key variable name, then per field
|
|
22
|
-
* written; nothing is written on a refusal.
|
|
36
|
+
* `keys` merges per key variable name, then per field; `models.<ENV>` is REPLACED WHOLE (`null`
|
|
37
|
+
* clears it). Validated before anything is written; nothing is written on a refusal.
|
|
23
38
|
*
|
|
24
|
-
* Patch fields understood: `monthlyLimitUsd` (finite > 0), `
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
39
|
+
* Patch fields understood: `monthlyLimitUsd` (finite > 0), `keys.<ENV>.{shape,baseUrl,legacyMaxTokens}`,
|
|
40
|
+
* `models.<ENV>` (a list judged by {@link modelsProblem}). The first write of a row's `models` list
|
|
41
|
+
* removes that row's older `name` / `priceInPerM` / `priceOutPerM` in the SAME write (never two
|
|
42
|
+
* sources); a retired top-level `anthropicBalanceNote` is dropped on any write. Any other field is
|
|
43
|
+
* kept, but the whole document is swept for secret-shaped strings first.
|
|
28
44
|
* @param {Record<string, any>} patch
|
|
29
45
|
* @param {{ home?: string }} [opts]
|
|
30
46
|
* @returns {Record<string, any>} the document as written
|
|
@@ -35,6 +51,7 @@ export function updateConfig(patch: Record<string, any>, opts?: {
|
|
|
35
51
|
/** A plain-words config failure (bad value, secret-shaped string, unreadable file). */
|
|
36
52
|
export class ConfigError extends Error {
|
|
37
53
|
}
|
|
54
|
+
export function cleanBaseUrl(v: string): string;
|
|
38
55
|
export type ConfigRead = {
|
|
39
56
|
/**
|
|
40
57
|
* the parsed document ({} when missing/unreadable)
|
package/types/declaredclose.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export function declaredStages(closeDecl: any): any[] | null;
|
|
|
53
53
|
*
|
|
54
54
|
* @param {any} closeDecl
|
|
55
55
|
* @param {{at?: string, listing?: string[]|null, deferListing?: boolean,
|
|
56
|
-
* catalogue?: Record<string, any>, verdictType?: string|null, writeScope?: string[]|null}} [opts]
|
|
56
|
+
* catalogue?: Record<string, any>, verdictType?: string|null, writeScope?: string[]|null, jobLines?: {n: number}[]|null}} [opts]
|
|
57
57
|
* @returns {{ok: boolean, reds: Red[], closeDecl: any, grounded: boolean,
|
|
58
58
|
* scoped: {scoped: boolean, via: string|null},
|
|
59
59
|
* ceiling: {class: string, kind: string, stage: string|null, locked: boolean}|null}}
|
|
@@ -65,6 +65,9 @@ export function validateCloseDecl(closeDecl: any, opts?: {
|
|
|
65
65
|
catalogue?: Record<string, any>;
|
|
66
66
|
verdictType?: string | null;
|
|
67
67
|
writeScope?: string[] | null;
|
|
68
|
+
jobLines?: {
|
|
69
|
+
n: number;
|
|
70
|
+
}[] | null;
|
|
68
71
|
}): {
|
|
69
72
|
ok: boolean;
|
|
70
73
|
reds: Red[];
|
package/types/draftspend.d.ts
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* One line of the drafting log. `no` = the step's position in the session's progress list (a step id can repeat).
|
|
3
3
|
* - `step-start` {no, id, label, at}
|
|
4
4
|
* - `step-end` {no, status: 'done'|'failed', label, at} (a re-opened step writes `step-reopen` {no, at} first)
|
|
5
|
-
* - `
|
|
5
|
+
* - `step-label` {no, label, at} (the step reads `label` from now on, status and times untouched: the thinking row's "the model thought anyway" / "can't change it" / "not confirmed")
|
|
6
|
+
* - `call` {no, step, label, model, thinking, thinkingSupport, thinkingStatus?, costUsd (null stays null), unpricedRounds, at}: one METERED model call
|
|
7
|
+
* (`thinking` = the tick's mode: off | on; `thinkingSupport` = bare-agent's lookup for the model: true | false | 'unverified';
|
|
8
|
+
* `thinkingStatus` = bare-agent's own verdict for the call's run: applied | unsupported | ignored | unknown, present only when thinkingMode was sent)
|
|
6
9
|
* (no token counts: the call path does not carry them without reworking the library, so none are recorded)
|
|
7
10
|
* @typedef {{kind: string, no: number, at: string, [k: string]: any}} DraftEvent
|
|
8
11
|
*/
|
|
@@ -105,7 +108,10 @@ export const DRAFT_LOG_FILE: "draft-log.jsonl";
|
|
|
105
108
|
* One line of the drafting log. `no` = the step's position in the session's progress list (a step id can repeat).
|
|
106
109
|
* - `step-start` {no, id, label, at}
|
|
107
110
|
* - `step-end` {no, status: 'done'|'failed', label, at} (a re-opened step writes `step-reopen` {no, at} first)
|
|
108
|
-
* - `
|
|
111
|
+
* - `step-label` {no, label, at} (the step reads `label` from now on, status and times untouched: the thinking row's "the model thought anyway" / "can't change it" / "not confirmed")
|
|
112
|
+
* - `call` {no, step, label, model, thinking, thinkingSupport, thinkingStatus?, costUsd (null stays null), unpricedRounds, at}: one METERED model call
|
|
113
|
+
* (`thinking` = the tick's mode: off | on; `thinkingSupport` = bare-agent's lookup for the model: true | false | 'unverified';
|
|
114
|
+
* `thinkingStatus` = bare-agent's own verdict for the call's run: applied | unsupported | ignored | unknown, present only when thinkingMode was sent)
|
|
109
115
|
* (no token counts: the call path does not carry them without reworking the library, so none are recorded)
|
|
110
116
|
*/
|
|
111
117
|
export type DraftEvent = {
|
package/types/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { validateEnvelope, resolveTrySpec, resolveReuse, reuseSpecHash, selectBr
|
|
|
15
15
|
export { classifyIncidents, foldLedger, ledgerDeltas, updateLedger, LEDGER_CLASSES, VOUCHED_RATE_SOURCES, rateProvenance, spendProvenance } from "./ledger.js";
|
|
16
16
|
export { readShimArm, READ_SHIM_CAP, READ_SHIM_STRATEGY, READ_SHIM_DIFF_STRATEGY } from "./readshim.js";
|
|
17
17
|
export { runDeclaredClose, runStage, seedRead, seedAtHead, LIVE_KINDS, STOP_FAULTS, JUDGED_MARKER, HUMAN_DECISIONS, SEED_EXEMPT_KINDS, normalizeHumanRuling, resolveHumanRuling, JUDGE_ATTEMPTS, MAX_JUDGED_PATHS, DOOR_OPEN_OUTCOMES, REVIEW_DOOR_CLASSES, doorOpens, mechanicalStages } from "./kinds.js";
|
|
18
|
-
export {
|
|
18
|
+
export { resolveJudge, JUDGE_RULES, JUDGE_RULE_IDS, runLocate, decide, CALIBRATION_SIZE, validateCalibrationSet, expectedOf } from "./judged.js";
|
|
19
19
|
export { proposeJudgedArtifacts, signJudgedArtifacts, foldJudgedArtifacts } from "./cardauthor.js";
|
|
20
20
|
export { runCalibration, INJECTION_LOCATE_BATTERY, CASUALTY_AXES } from "./calibrate.js";
|
|
21
21
|
export { validateDeclaration, KIND_CATALOGUE, LOCKED_KINDS, genreEnv, genreInstruments, LOCKED_CLASSES, CLASS_BATTERIES, classGuards, closeCeiling, NEVER_OFFERED_KINDS } from "./authoring.js";
|
package/types/job.d.ts
CHANGED
|
@@ -122,18 +122,18 @@ export function checkApproval(job: object, approvals: unknown): boolean;
|
|
|
122
122
|
* mismatched flag is a mistake worth stopping on, never a silent swap); the
|
|
123
123
|
* same id from both is not a conflict. Extracted from scripts/run-u.mjs so
|
|
124
124
|
* the decision is testable without running the script or touching a provider.
|
|
125
|
-
* @param {{ specModel?: string, flagModel?: string,
|
|
125
|
+
* @param {{ specModel?: string, flagModel?: string, suppliedModel?: string }} args
|
|
126
126
|
* `specModel` — `job.model` if the signed spec carries one, else undefined.
|
|
127
127
|
* `flagModel` — the model id an explicit `--model <tier>` resolved to, else
|
|
128
128
|
* undefined (a flag that was never passed, not merely a default tier name).
|
|
129
|
-
* `
|
|
129
|
+
* `suppliedModel` — a model the CALLER supplies when neither spec nor flag says (bareloop keeps none of its own).
|
|
130
130
|
* @returns {{ model: string, source: 'spec'|'flag'|'default' }}
|
|
131
|
-
* @throws {Error} when the spec names a model and the flag names a different one
|
|
131
|
+
* @throws {Error} when the spec names a model and the flag names a different one, or when no model is named at all
|
|
132
132
|
*/
|
|
133
|
-
export function resolveWorkerModel({ specModel, flagModel,
|
|
133
|
+
export function resolveWorkerModel({ specModel, flagModel, suppliedModel }: {
|
|
134
134
|
specModel?: string;
|
|
135
135
|
flagModel?: string;
|
|
136
|
-
|
|
136
|
+
suppliedModel?: string;
|
|
137
137
|
}): {
|
|
138
138
|
model: string;
|
|
139
139
|
source: "spec" | "flag" | "default";
|
|
@@ -272,7 +272,7 @@ export const PROVIDERS: readonly string[];
|
|
|
272
272
|
export const CONDITION_KEYS: readonly string[];
|
|
273
273
|
/**
|
|
274
274
|
* The fields a "Reuse workflow" run may change: where the work lands (the write fence, `writeScope`, and a
|
|
275
|
-
* `destination`/`source` where a spec ever carries them) and the two ceilings. Everything else in a signed spec is
|
|
275
|
+
* `destination`/`source` where a spec ever carries them), the `inputs` the person pointed at (P7: Inputs is open on a reuse) and the two ceilings. Everything else in a signed spec is
|
|
276
276
|
* the WORKFLOW — goal, checks, guardrails, close (the worker model is the third kind, {@link WORKFLOW_KEY_IDENTITY_FIELDS}). ONE list, shared by {@link workflowKey} and by the panel's
|
|
277
277
|
* reuse (so what the key ignores is exactly what the person may edit, never two spellings).
|
|
278
278
|
*/
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse "The job" box. A plain line is a numbered job line (1, 2, 3...). A line starting `~` has no number and belongs
|
|
3
|
+
* to the numbered line above; consecutive `~` lines become ONE rule joined with `'; '`. A `~` line starting `PASS:` or
|
|
4
|
+
* `FAIL:` is also a judge example (kept with its line number); any other `~` line is a guardrail. Empty lines are
|
|
5
|
+
* ignored. A `~` before line 1 is a red.
|
|
6
|
+
* @param {unknown} text the box's raw text
|
|
7
|
+
* @returns {{ok: true, lines: JobLine[]}|{ok: false, error: string}}
|
|
8
|
+
*/
|
|
9
|
+
export function parseJobBlock(text: unknown): {
|
|
10
|
+
ok: true;
|
|
11
|
+
lines: JobLine[];
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Parse the "Inputs" box: one `label: value` per line, numbered 1, 2, 3 in the order written. Empty lines are ignored.
|
|
18
|
+
* This only checks the SHAPE — what a value must point at (line 1 an absolute repo, lines 2+ tracked files inside it)
|
|
19
|
+
* is proven by the panel at $0.
|
|
20
|
+
* @param {unknown} text
|
|
21
|
+
* @returns {{ok: true, inputs: JobInput[]}|{ok: false, error: string}}
|
|
22
|
+
*/
|
|
23
|
+
export function parseInputs(text: unknown): {
|
|
24
|
+
ok: true;
|
|
25
|
+
inputs: JobInput[];
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The person's job lines as the drafter reads them (answer 1 of the interview): each numbered line, then its rule
|
|
32
|
+
* (the `~` lines joined) indented under it. One spelling, so the number the person typed beside a line is the number a
|
|
33
|
+
* stage's `fromLine` names.
|
|
34
|
+
* @param {JobLine[]} lines
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
export function renderJobLines(lines: JobLine[]): string;
|
|
38
|
+
/**
|
|
39
|
+
* The PASS:/FAIL: examples the person wrote, each kept with its line number (answer 2 of a rubric interview — what the
|
|
40
|
+
* calibration compile reads). Empty string when there are none.
|
|
41
|
+
* @param {JobLine[]} lines
|
|
42
|
+
* @returns {string}
|
|
43
|
+
*/
|
|
44
|
+
export function renderExamples(lines: JobLine[]): string;
|
|
45
|
+
/**
|
|
46
|
+
* The inputs as the drafter is told about them: "the person pointed at these inputs: N label path".
|
|
47
|
+
* @param {JobInput[]} inputs
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
export function renderInputs(inputs: JobInput[]): string;
|
|
51
|
+
/**
|
|
52
|
+
* The two cross-checks between a parsed job block and the Check type: a RUBRIC job needs at least one `PASS:` and one
|
|
53
|
+
* `FAIL:` example (the calibration compile reads them); a DETERMINISTIC job has no judge, so an example line would be
|
|
54
|
+
* silently dropped — a red instead.
|
|
55
|
+
* @param {JobLine[]} lines
|
|
56
|
+
* @param {boolean} rubric
|
|
57
|
+
* @returns {string|null} the plain red, or null when the block fits the Check type
|
|
58
|
+
*/
|
|
59
|
+
export function jobBlockFitsCheck(lines: JobLine[], rubric: boolean): string | null;
|
|
60
|
+
/**
|
|
61
|
+
* The signed `jobLines` field from parsed lines: the person's own words, `{n, text, rule, rules}` (examples stay inside the
|
|
62
|
+
* rule text, where the person wrote them). `rules` is the same `~` lines as an array, BESIDE the joined `rule` (never
|
|
63
|
+
* replacing it); it is omitted on a line with no `~` line, and an older spec lacks it entirely.
|
|
64
|
+
* @param {JobLine[]} lines
|
|
65
|
+
* @returns {{n: number, text: string, rule: string, rules?: string[]}[]}
|
|
66
|
+
*/
|
|
67
|
+
export function signedJobLines(lines: JobLine[]): {
|
|
68
|
+
n: number;
|
|
69
|
+
text: string;
|
|
70
|
+
rule: string;
|
|
71
|
+
rules?: string[];
|
|
72
|
+
}[];
|
|
73
|
+
/** @typedef {{verdict: 'PASS'|'FAIL', text: string}} JobExample a `~ PASS:` / `~ FAIL:` line (rubric only), kept with its job line */
|
|
74
|
+
/** @typedef {{n: number, text: string, rule: string, rules: string[], examples: JobExample[]}} JobLine one numbered job line; `rule` = its `~` lines joined with '; ' ('' when none), `rules` = those same `~` lines one by one (so an example's own '; ' survives) */
|
|
75
|
+
/** @typedef {{n: number, label: string, value: string}} JobInput one numbered `label: value` input line */
|
|
76
|
+
/** the joiner for consecutive `~` lines (fwd's joinGuardrails) */
|
|
77
|
+
export const RULE_JOINER: "; ";
|
|
78
|
+
/**
|
|
79
|
+
* a `~ PASS:` / `~ FAIL:` line (rubric only), kept with its job line
|
|
80
|
+
*/
|
|
81
|
+
export type JobExample = {
|
|
82
|
+
verdict: "PASS" | "FAIL";
|
|
83
|
+
text: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* one numbered job line; `rule` = its `~` lines joined with '; ' ('' when none), `rules` = those same `~` lines one by one (so an example's own '; ' survives)
|
|
87
|
+
*/
|
|
88
|
+
export type JobLine = {
|
|
89
|
+
n: number;
|
|
90
|
+
text: string;
|
|
91
|
+
rule: string;
|
|
92
|
+
rules: string[];
|
|
93
|
+
examples: JobExample[];
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* one numbered `label: value` input line
|
|
97
|
+
*/
|
|
98
|
+
export type JobInput = {
|
|
99
|
+
n: number;
|
|
100
|
+
label: string;
|
|
101
|
+
value: string;
|
|
102
|
+
};
|
package/types/judged.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* item 31.4 a green job runs on its own key alone, and this is what lets a
|
|
18
18
|
* JUDGED one do the same.
|
|
19
19
|
*
|
|
20
|
-
* There is deliberately NO third fallback to
|
|
20
|
+
* There is deliberately NO third fallback to a library-pinned model. A caller that cannot
|
|
21
21
|
* say which model will grade has not wired a judge, and the grading path stops
|
|
22
22
|
* as a wiring gap rather than grading under an identity nobody chose — the same
|
|
23
23
|
* answer an absent `judgeLoop` already gets. A silent default here would be the
|
|
@@ -79,7 +79,7 @@ export function resolveJudge({ specJudge, workerProvider, workerModel }?: {
|
|
|
79
79
|
*
|
|
80
80
|
* @param {{provider?: string, model?: string, judge?: any}} source draft or spec
|
|
81
81
|
* @param {string} fallbackProviderName used only when `source.provider` is absent
|
|
82
|
-
* @param {(o: {specModel?: string, flagModel?: string,
|
|
82
|
+
* @param {(o: {specModel?: string, flagModel?: string, suppliedModel?: string}) => {model: string, source: string}} resolveWorkerModelFn `resolveWorkerModel` from `./job.js`
|
|
83
83
|
* @returns {{provider: string, model: string}}
|
|
84
84
|
*/
|
|
85
85
|
export function resolveJobJudge(source: {
|
|
@@ -89,7 +89,7 @@ export function resolveJobJudge(source: {
|
|
|
89
89
|
}, fallbackProviderName: string, resolveWorkerModelFn: (o: {
|
|
90
90
|
specModel?: string;
|
|
91
91
|
flagModel?: string;
|
|
92
|
-
|
|
92
|
+
suppliedModel?: string;
|
|
93
93
|
}) => {
|
|
94
94
|
model: string;
|
|
95
95
|
source: string;
|
|
@@ -309,38 +309,6 @@ export function decide(facts: any, card: any, { artifactText }?: {
|
|
|
309
309
|
firstRed: string | null;
|
|
310
310
|
reason: string | null;
|
|
311
311
|
};
|
|
312
|
-
/**
|
|
313
|
-
* THE JUDGE'S HISTORICAL PIN. Until PRD item 32 (2026-09-10) this constant WAS
|
|
314
|
-
* the judge: every grading path imported it, so bareloop could run a worker on
|
|
315
|
-
* any provider and still judge only on Claude.
|
|
316
|
-
*
|
|
317
|
-
* It is no longer read by any grading path. The judge identity is now RESOLVED
|
|
318
|
-
* per job (`resolveJudge` below) and travels as data — `ctx.judgeModel` into
|
|
319
|
-
* `runJudgedFloor`, an explicit argument into the calibration gate, and
|
|
320
|
-
* `closeDecl.calibration.judgeModel` into the signed spec, exactly as before.
|
|
321
|
-
* Keeping the export is deliberate: it is part of the public API
|
|
322
|
-
* (`src/index.js`) and an adopter importing it should not break on a minor.
|
|
323
|
-
* What it means now is "the judge bareloop pinned before item 32", which is
|
|
324
|
-
* still the right DEFAULT for an anthropic-api job and still the only tier with
|
|
325
|
-
* established injection resistance upstream (BA-20's `INJECTION_BATTERY` is
|
|
326
|
-
* haiku-4.5 only).
|
|
327
|
-
*
|
|
328
|
-
* THE ENFORCEMENT IS UNCHANGED, and still lives in three wired places because a
|
|
329
|
-
* rule with no detector is prose (F45) — only the value being compared moved
|
|
330
|
-
* from this constant to the resolved identity:
|
|
331
|
-
* 1. the identity is STORED with the set it graded — `foldJudgedArtifacts`
|
|
332
|
-
* writes it as `closeDecl.calibration.judgeModel`, inside the spec, so
|
|
333
|
-
* `jobSpecHash` covers it by construction. Change the judge and every
|
|
334
|
-
* signed judged spec hashes differently: the signature dies, and re-signing
|
|
335
|
-
* is what re-runs the calibration gate.
|
|
336
|
-
* 2. `validateCloseDecl` REQUIRES it on any stored set — a set nobody can
|
|
337
|
-
* attribute to a judge is a floor nobody can tell apart from a moved one.
|
|
338
|
-
* 3. `runJudgedFloor` refuses to grade when the stored identity is not the one
|
|
339
|
-
* about to grade, naming both. It does not degrade in either direction:
|
|
340
|
-
* grading on the new judge judges against a floor nobody calibrated, and
|
|
341
|
-
* the old judge is not on offer.
|
|
342
|
-
*/
|
|
343
|
-
export const JUDGE_MODEL: "claude-haiku-4-5";
|
|
344
312
|
/**
|
|
345
313
|
* The locate call's token ceiling. The POC's two real artifacts came back well
|
|
346
314
|
* inside 2000; this doubles that for headroom on a longer artifact, and the
|
|
@@ -402,13 +370,14 @@ export const JUDGE_RULE_IDS: readonly string[];
|
|
|
402
370
|
export const CALIBRATION_SIZE: 10;
|
|
403
371
|
/** the two verdicts a case may expect — `decide()`'s own closed set */
|
|
404
372
|
export const CASE_VERDICTS: readonly string[];
|
|
405
|
-
export function defaultJudgeLoop({ provider, system, rates }: {
|
|
373
|
+
export function defaultJudgeLoop({ provider, system, rates, thinking }: {
|
|
406
374
|
provider: any;
|
|
407
375
|
system: string;
|
|
408
376
|
rates?: {
|
|
409
377
|
in: number;
|
|
410
378
|
out: number;
|
|
411
379
|
} | null;
|
|
380
|
+
thinking?: boolean;
|
|
412
381
|
}): {
|
|
413
382
|
run: (msgs: any[], tools: any[], opts?: any) => Promise<any>;
|
|
414
383
|
};
|
package/types/keysfile.d.ts
CHANGED
|
@@ -25,19 +25,20 @@ export function parseKeysText(text: string): Record<string, string>;
|
|
|
25
25
|
*/
|
|
26
26
|
export function filledKeyNames(home?: string): string[];
|
|
27
27
|
/**
|
|
28
|
-
* Create the keys file with
|
|
29
|
-
* exist (mode 600). An existing file is never touched.
|
|
30
|
-
* @param {readonly string[]} presetNames the names to seed, in order
|
|
28
|
+
* Create the keys file with {@link KEYS_FILE_BODY} when — and only when — it does not
|
|
29
|
+
* exist (mode 600, dir 700). An existing file is never touched.
|
|
31
30
|
* @param {string} [home]
|
|
32
31
|
* @returns {boolean} true if it was created
|
|
33
32
|
*/
|
|
34
|
-
export function ensureKeysFile(
|
|
33
|
+
export function ensureKeysFile(home?: string): boolean;
|
|
35
34
|
/**
|
|
36
35
|
* @typedef {object} KeysLoad
|
|
37
36
|
* @property {boolean} exists the file is there
|
|
38
37
|
* @property {string[]} names the NAMES the file defines (sorted; never values)
|
|
39
38
|
* @property {string|null} warning a plain-words warning (file readable by others, or
|
|
40
39
|
* unreadable), else null — a warning, never a refusal
|
|
40
|
+
* @property {boolean} [unreadable] true only when the file is there but could not be read (the Settings row then
|
|
41
|
+
* reads "refused — see above"); absent otherwise
|
|
41
42
|
* @property {Record<string,string|undefined>} env shell env with the file filling the
|
|
42
43
|
* names the shell does not set. THE ONLY place values leave this module.
|
|
43
44
|
*/
|
|
@@ -68,6 +69,11 @@ export function keysForDoor(deps: {
|
|
|
68
69
|
env: Record<string, string | undefined>;
|
|
69
70
|
home: string | undefined;
|
|
70
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* The two comment lines a fresh keys file is created with — no provider name, no preset key.
|
|
74
|
+
* Each key the person types becomes a row in Settings > Providers.
|
|
75
|
+
*/
|
|
76
|
+
export const KEYS_FILE_BODY: string;
|
|
71
77
|
export type KeysLoad = {
|
|
72
78
|
/**
|
|
73
79
|
* the file is there
|
|
@@ -82,6 +88,11 @@ export type KeysLoad = {
|
|
|
82
88
|
* unreadable), else null — a warning, never a refusal
|
|
83
89
|
*/
|
|
84
90
|
warning: string | null;
|
|
91
|
+
/**
|
|
92
|
+
* true only when the file is there but could not be read (the Settings row then
|
|
93
|
+
* reads "refused — see above"); absent otherwise
|
|
94
|
+
*/
|
|
95
|
+
unreadable?: boolean | undefined;
|
|
85
96
|
/**
|
|
86
97
|
* shell env with the file filling the
|
|
87
98
|
* names the shell does not set. THE ONLY place values leave this module.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The key goes only in a header, in the form each shape expects.
|
|
3
|
+
* @param {string} shape an API shape id (src/providershapes.js)
|
|
4
|
+
* @param {string} key
|
|
5
|
+
* @returns {Record<string, string>}
|
|
6
|
+
*/
|
|
7
|
+
export function authHeaders(shape: string, key: string): Record<string, string>;
|
|
8
|
+
/**
|
|
9
|
+
* The model ids a provider's list answer holds, per API shape (`data[].id` for two shapes;
|
|
10
|
+
* `models[].name` minus its `models/` prefix for the third). Sorted, de-duplicated.
|
|
11
|
+
* @param {string} shape
|
|
12
|
+
* @param {any} body
|
|
13
|
+
* @returns {string[]}
|
|
14
|
+
*/
|
|
15
|
+
export function idsOf(shape: string, body: any): string[];
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{ ok: true, models: string[], ms: number }
|
|
18
|
+
* | { ok: false, why: string, status: string, detail?: string }} ListResult
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* One free GET of `<baseUrl>/models` with the key in the header only and a deadline.
|
|
22
|
+
* Failure is data, never a throw: `why` is a plain sentence, `status` a short machine word
|
|
23
|
+
* (`no-base-url`, `redirect`, `HTTP <n>`, `timeout`, `unreachable`) for callers that need it.
|
|
24
|
+
* @param {object} o
|
|
25
|
+
* @param {string} o.shape an API shape id
|
|
26
|
+
* @param {string} o.baseUrl the row's Base URL ('' = no call)
|
|
27
|
+
* @param {string} o.key the key value (header only)
|
|
28
|
+
* @param {typeof fetch} [o.fetchImpl] test seam; defaults to the global `fetch`
|
|
29
|
+
* @param {number} [o.timeoutMs]
|
|
30
|
+
* @returns {Promise<ListResult>}
|
|
31
|
+
*/
|
|
32
|
+
export function listModels({ shape, baseUrl, key, fetchImpl, timeoutMs }: {
|
|
33
|
+
shape: string;
|
|
34
|
+
baseUrl: string;
|
|
35
|
+
key: string;
|
|
36
|
+
fetchImpl?: typeof fetch | undefined;
|
|
37
|
+
timeoutMs?: number | undefined;
|
|
38
|
+
}): Promise<ListResult>;
|
|
39
|
+
/** The default deadline for the one GET. */
|
|
40
|
+
export const LIST_TIMEOUT_MS: 4000;
|
|
41
|
+
export type ListResult = {
|
|
42
|
+
ok: true;
|
|
43
|
+
models: string[];
|
|
44
|
+
ms: number;
|
|
45
|
+
} | {
|
|
46
|
+
ok: false;
|
|
47
|
+
why: string;
|
|
48
|
+
status: string;
|
|
49
|
+
detail?: string;
|
|
50
|
+
};
|
package/types/monthly.d.ts
CHANGED
|
@@ -48,11 +48,11 @@ export function monthSpend(opts?: {
|
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
50
|
* The Money tab's figures: all-time and this-month spend, and per-provider breakdown
|
|
51
|
-
* (
|
|
52
|
-
* pooled into another row). Any leg with unknown spend makes the figure it belongs to
|
|
51
|
+
* (grouped by the matched Providers row's key variable name; a run on no row lands under its
|
|
52
|
+
* own provider name, never pooled into another row). Any leg with unknown spend makes the figure it belongs to
|
|
53
53
|
* an "at least".
|
|
54
54
|
* @param {{ home?: string, sessionsRoot?: string, now?: () => number, rows?: readonly import('./providerrows.js').KeyRow[] }} [opts] `rows` = the Providers rows: when given, `tokensByRow` sums each row's tokens
|
|
55
|
-
* @returns {{ tokensByRow: Record<string, number>, total: {usd: number, atLeast: boolean, tokens: number}, month: {usd: number, atLeast: boolean, tokens: number},
|
|
55
|
+
* @returns {{ tokensByRow: Record<string, number>, tokensByModel: Record<string, Record<string, number>>, total: {usd: number, atLeast: boolean, tokens: number}, month: {usd: number, atLeast: boolean, tokens: number},
|
|
56
56
|
* byProvider: Record<string, {label: string, monthUsd: number, monthAtLeast: boolean, totalUsd: number, totalAtLeast: boolean, tokens: number, vouchedRounds: number, otherRounds: number, monthWallMs: number|null, monthWallAtLeast: boolean, totalWallMs: number|null, totalWallAtLeast: boolean}> }}
|
|
57
57
|
*/
|
|
58
58
|
export function spendSummary(opts?: {
|
|
@@ -62,6 +62,7 @@ export function spendSummary(opts?: {
|
|
|
62
62
|
rows?: readonly import("./providerrows.js").KeyRow[];
|
|
63
63
|
}): {
|
|
64
64
|
tokensByRow: Record<string, number>;
|
|
65
|
+
tokensByModel: Record<string, Record<string, number>>;
|
|
65
66
|
total: {
|
|
66
67
|
usd: number;
|
|
67
68
|
atLeast: boolean;
|