bareloop 0.41.0 → 0.42.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 +63 -1
- package/README.md +13 -21
- package/bareloop.context.md +44 -4
- package/package.json +4 -3
- package/src/authorflow.js +337 -29
- package/src/authoring.js +92 -7
- package/src/authorjob.js +78 -16
- package/src/authorreadout.js +89 -5
- package/src/authorrun.js +14 -5
- package/src/authorscout.js +108 -0
- package/src/declaredclose.js +23 -12
- package/src/facts.js +317 -0
- package/src/factwords.js +129 -0
- package/src/inputlook.js +301 -0
- package/src/job.js +2 -1
- package/src/jobblock.js +7 -2
- package/src/kinds.js +84 -3
- package/src/labelscan.js +170 -0
- package/src/pagefetch.js +125 -0
- package/src/panel/authorroutes.js +15 -2
- package/src/panel/authorsession.js +99 -22
- package/src/panel/index.html +33 -7
- package/src/panel/jobplan.js +34 -11
- package/src/panel/server.js +19 -3
- package/src/planrun.js +3 -2
- package/src/rubricstep.js +804 -0
- package/src/source.js +166 -1
- package/src/u-readout.js +1 -1
- package/src/userrun.js +14 -2
- package/types/authorflow.d.ts +267 -13
- package/types/authoring.d.ts +29 -1
- package/types/authorjob.d.ts +7 -5
- package/types/authorreadout.d.ts +27 -2
- package/types/authorscout.d.ts +70 -0
- package/types/declaredclose.d.ts +4 -2
- package/types/facts.d.ts +71 -0
- package/types/factwords.d.ts +42 -0
- package/types/inputlook.d.ts +238 -0
- package/types/jobblock.d.ts +8 -1
- package/types/labelscan.d.ts +38 -0
- package/types/pagefetch.d.ts +71 -0
- package/types/panel/authorsession.d.ts +18 -2
- package/types/panel/jobplan.d.ts +12 -4
- package/types/panel/server.d.ts +4 -2
- package/types/rubricstep.d.ts +286 -0
- package/types/source.d.ts +94 -0
- package/types/userrun.d.ts +11 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** @typedef {{id: string, label: string, count: number, example: string}} LabelEntry */
|
|
2
|
+
/** @typedef {Record<'money'|'number'|'date'|'time'|'text', LabelEntry[]>} LabelScan */
|
|
3
|
+
/** @param {string} t @returns {string} white space made one space, quote marks at the edges dropped, trimmed - how a label is compared */
|
|
4
|
+
export function normLabel(t: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Scan one source text for the labels that sit before values, per shape.
|
|
7
|
+
* @param {string} text
|
|
8
|
+
* @returns {LabelScan}
|
|
9
|
+
*/
|
|
10
|
+
export function scanLabels(text: string): LabelScan;
|
|
11
|
+
/**
|
|
12
|
+
* Is this label on the list for this shape? Compared the way a label is read: white space of any kind is one space, quote marks at the
|
|
13
|
+
* edges are dropped. `idOrText` may be a list id (`t1`) or the exact words.
|
|
14
|
+
* @param {LabelScan} scan @param {string} shape @param {unknown} idOrText
|
|
15
|
+
* @returns {LabelEntry|null}
|
|
16
|
+
*/
|
|
17
|
+
export function labelOnList(scan: LabelScan, shape: string, idOrText: unknown): LabelEntry | null;
|
|
18
|
+
/**
|
|
19
|
+
* The list as the look and the drafter are shown it, one block per shape that has any label.
|
|
20
|
+
* @param {string} inputLabel the input the list belongs to @param {LabelScan} scan
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
export function renderLabelList(inputLabel: string, scan: LabelScan): string;
|
|
24
|
+
/** the shapes a list is made for */
|
|
25
|
+
export const LABEL_SHAPES: readonly string[];
|
|
26
|
+
/** a label must occur at least this often to be listed (1: a one-page document with one total still has its label; the list is cut to the highest counts) */
|
|
27
|
+
export const MIN_COUNT: 1;
|
|
28
|
+
/** how many labels one shape's list holds at most (the highest counts first) */
|
|
29
|
+
export const MAX_PER_SHAPE: 40;
|
|
30
|
+
/** only this much of a source is scanned (a source over it is scanned up to a line end) */
|
|
31
|
+
export const SCAN_MAX_CHARS: 2000000;
|
|
32
|
+
export type LabelEntry = {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
count: number;
|
|
36
|
+
example: string;
|
|
37
|
+
};
|
|
38
|
+
export type LabelScan = Record<"money" | "number" | "date" | "time" | "text", LabelEntry[]>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** @param {unknown} v @returns {boolean} an http(s) address (the one spelling of "this Inputs value is a web address") */
|
|
2
|
+
export function isWebUrl(v: unknown): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* How much of a fetched page is the page's own content: the snapshot's header lines (url, size note, hint) and every part of the tree
|
|
5
|
+
* under a banner / navigation / contentinfo landmark are taken out, the page reader's bracketed tags are removed, and what is left is
|
|
6
|
+
* counted. Generic - no site names, only the ARIA landmark roles. Text that is not a snapshot tree (a plain file) has no landmark, so it
|
|
7
|
+
* counts whole.
|
|
8
|
+
* @param {string} text @returns {number}
|
|
9
|
+
*/
|
|
10
|
+
export function pageContentChars(text: string): number;
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{goto: (url: string, timeout?: number) => Promise<void>, waitForNetworkIdle: (o?: {idle?: number, timeout?: number}) => Promise<void>,
|
|
13
|
+
* snapshot: (o?: {mode?: string}) => Promise<string>, close: () => Promise<void>}} FetchPage the part of barebrowse's page handle the fetch uses
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Fetch one page's text. `connect` is injected (a test never reaches the network); the default is barebrowse's own `connect`.
|
|
17
|
+
* @param {string} url
|
|
18
|
+
* @param {{connect?: (opts: Record<string, any>) => Promise<FetchPage>, timeoutMs?: number, idleMs?: number, idleTimeoutMs?: number, closeWaitMs?: number}} [o]
|
|
19
|
+
* @returns {Promise<{ok: true, text: string, url: string}|{ok: false, error: string}>} `error` is plain words, without a spend line
|
|
20
|
+
*/
|
|
21
|
+
export function fetchPageText(url: string, { connect, timeoutMs, idleMs, idleTimeoutMs, closeWaitMs }?: {
|
|
22
|
+
connect?: (opts: Record<string, any>) => Promise<FetchPage>;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
idleMs?: number;
|
|
25
|
+
idleTimeoutMs?: number;
|
|
26
|
+
closeWaitMs?: number;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
ok: true;
|
|
29
|
+
text: string;
|
|
30
|
+
url: string;
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
error: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** the session options (incognito: no auth ever enters; blockPrivateNetwork: SSRF guard); ONE frozen object so a test can pin them */
|
|
36
|
+
export const CONNECT_OPTIONS: Readonly<{
|
|
37
|
+
incognito: true;
|
|
38
|
+
blockPrivateNetwork: true;
|
|
39
|
+
}>;
|
|
40
|
+
/** the snapshot options step 0 proved */
|
|
41
|
+
export const SNAPSHOT_OPTIONS: Readonly<{
|
|
42
|
+
mode: "act";
|
|
43
|
+
}>;
|
|
44
|
+
/** the page's network must be quiet this long (ms) before we read it: long enough to span the gap between a page's first load and the
|
|
45
|
+
* script requests that fill the results, short enough not to stretch a plain page */
|
|
46
|
+
export const NETWORK_IDLE_MS: 1500;
|
|
47
|
+
/** the most we wait for the network to go quiet (ms); a page that never settles (polling, streaming) is read as it stands after this */
|
|
48
|
+
export const NETWORK_IDLE_TIMEOUT_MS: 20000;
|
|
49
|
+
/** the most we wait for the page to load at all (ms) */
|
|
50
|
+
export const GOTO_TIMEOUT_MS: 30000;
|
|
51
|
+
/** a page that comes back with fewer characters than this (after trimming) is treated as "nothing came back" */
|
|
52
|
+
export const MIN_PAGE_CHARS: 200;
|
|
53
|
+
/** the page text left after the site's own header, menus and footer are taken out must hold at least this many characters, or the page is
|
|
54
|
+
* "only site chrome" (L2: a 719-character fetch of Google's header and sign-in passed the 200-character floor) */
|
|
55
|
+
export const MIN_CONTENT_CHARS: 100;
|
|
56
|
+
/** our own deadline around one whole fetch (a hung browser leaves no trace; this is the only thing that fires on the absence of an answer) */
|
|
57
|
+
export const PAGE_FETCH_TIMEOUT_MS: 90000;
|
|
58
|
+
/**
|
|
59
|
+
* the part of barebrowse's page handle the fetch uses
|
|
60
|
+
*/
|
|
61
|
+
export type FetchPage = {
|
|
62
|
+
goto: (url: string, timeout?: number) => Promise<void>;
|
|
63
|
+
waitForNetworkIdle: (o?: {
|
|
64
|
+
idle?: number;
|
|
65
|
+
timeout?: number;
|
|
66
|
+
}) => Promise<void>;
|
|
67
|
+
snapshot: (o?: {
|
|
68
|
+
mode?: string;
|
|
69
|
+
}) => Promise<string>;
|
|
70
|
+
close: () => Promise<void>;
|
|
71
|
+
};
|
|
@@ -7,8 +7,9 @@ export function latestStep(steps: StepLine[], id: string): StepLine | undefined;
|
|
|
7
7
|
* earlier line keeps its status and detail). Existing lines are never moved. Re-starting the step that is still the
|
|
8
8
|
* LAST line just resumes that line.
|
|
9
9
|
* @param {StepLine[]} steps @param {string} id @param {string} [detail] (absent = keep what the line has)
|
|
10
|
+
* @param {Readonly<Record<string, string>>} [labels] the label table (a file job passes its own)
|
|
10
11
|
*/
|
|
11
|
-
export function advanceSteps(steps: StepLine[], id: string, detail?: string): void;
|
|
12
|
+
export function advanceSteps(steps: StepLine[], id: string, detail?: string, labels?: Readonly<Record<string, string>>): void;
|
|
12
13
|
/**
|
|
13
14
|
* The confirm turn's plan as a chat message (P7): a STRUCTURED `{role:'bot', kind:'plan', plan}` the page draws with the
|
|
14
15
|
* same renderer the Job tab uses — each numbered job line, its `~` rule, its drafted checks folded; the AI's own "not
|
|
@@ -139,7 +140,7 @@ export function validateJobCard(card: any, opts?: {
|
|
|
139
140
|
* @param {any} card the validated job card (see {@link validateJobCard})
|
|
140
141
|
* @param {{env?: Record<string,string|undefined>, sessionsRoot?: string, home?: string, timeoutMs?: number,
|
|
141
142
|
* scout?: any, generate?: Function, confirmGenerate?: Function, authorFn?: Function,
|
|
142
|
-
* prepareSigningFn?: Function, npmCiFn?: Function, draftThinking?: "on"|"off", reuse?: {spec: any, workflowKey: string}}} [deps] `scout`..`prepareSigningFn` are
|
|
143
|
+
* prepareSigningFn?: Function, npmCiFn?: Function, lookFn?: Function|null, fetchUrl?: (url: string) => Promise<{ok: true, text: string, url: string}|{ok: false, error: string}>, draftThinking?: "on"|"off", reuse?: {spec: any, workflowKey: string}}} [deps] `scout`..`prepareSigningFn` are
|
|
143
144
|
* TEST SEAMS ONLY — see the note just above where each is read, below. `reuse` (Reuse workflow) is NOT a seam: the
|
|
144
145
|
* caller (`/api/author/start`) sets it only when the server's own same-job rule held.
|
|
145
146
|
* @returns {any} the session object
|
|
@@ -155,6 +156,15 @@ export function createSession(card: any, deps?: {
|
|
|
155
156
|
authorFn?: Function;
|
|
156
157
|
prepareSigningFn?: Function;
|
|
157
158
|
npmCiFn?: Function;
|
|
159
|
+
lookFn?: Function | null;
|
|
160
|
+
fetchUrl?: (url: string) => Promise<{
|
|
161
|
+
ok: true;
|
|
162
|
+
text: string;
|
|
163
|
+
url: string;
|
|
164
|
+
} | {
|
|
165
|
+
ok: false;
|
|
166
|
+
error: string;
|
|
167
|
+
}>;
|
|
158
168
|
draftThinking?: "on" | "off";
|
|
159
169
|
reuse?: {
|
|
160
170
|
spec: any;
|
|
@@ -168,6 +178,12 @@ export function createSession(card: any, deps?: {
|
|
|
168
178
|
* @type {Readonly<Record<string, string>>}
|
|
169
179
|
*/
|
|
170
180
|
export const STEP_LABELS: Readonly<Record<string, string>>;
|
|
181
|
+
/**
|
|
182
|
+
* The same steps, worded for a job on the person's own local FILES (Part 1a): there is no worktree and no repo to read.
|
|
183
|
+
* Code-owned, one table beside STEP_LABELS; a step with no entry keeps its STEP_LABELS word.
|
|
184
|
+
* @type {Readonly<Record<string, string>>}
|
|
185
|
+
*/
|
|
186
|
+
export const FILE_JOB_STEP_LABELS: Readonly<Record<string, string>>;
|
|
171
187
|
/**
|
|
172
188
|
* The library's own `onPhase(name, ...)` calls (`src/authorjob.js`/`src/authorflow.js`) -> the step each one advances.
|
|
173
189
|
* A phase with no entry leaves the current step as it was.
|
package/types/panel/jobplan.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @typedef {{name: string, cls: 'machine check'|'judge'|null}} PlanCheck */
|
|
2
|
-
/** @typedef {{n: number, text: string, rule: string, checks: PlanCheck[], refused: string[]}} PlanLine */
|
|
2
|
+
/** @typedef {{n: number, text: string, rule: string, rules: string[], checks: PlanCheck[], refused: string[]}} PlanLine */
|
|
3
3
|
/** @typedef {{lines: PlanLine[], loose: PlanCheck[], notChecked: string[], alwaysOn: string[], older: boolean, goal?: string}} JobPlan */
|
|
4
4
|
/**
|
|
5
5
|
* `machine check` for a kind a command decides, `judge` for one that needs judgement; `null` for a stage whose kind is
|
|
@@ -8,9 +8,15 @@
|
|
|
8
8
|
* @returns {'machine check'|'judge'|null}
|
|
9
9
|
*/
|
|
10
10
|
export function checkClassOfKind(kind: unknown): "machine check" | "judge" | null;
|
|
11
|
+
/**
|
|
12
|
+
* The `~` rules of one job line, each on its own (the page draws one `~` row per rule): the line's own `rules` array when it
|
|
13
|
+
* has one (a rule may itself contain "; "), else the joined `rule` split on "; " (an older line that saved only the join).
|
|
14
|
+
* @param {any} l @returns {string[]}
|
|
15
|
+
*/
|
|
16
|
+
export function rulesOfLine(l: any): string[];
|
|
11
17
|
/**
|
|
12
18
|
* The plan of a SIGNED spec. With `jobLines`, each stage lands under EACH line its `fromLine` array names (a stage with none is
|
|
13
|
-
* a mandatory guard: "Always
|
|
19
|
+
* a mandatory guard: "Always checked"), `closeDecl.refused` reasons land under their line, and `closeDecl.notes` are the
|
|
14
20
|
* drafter's own "not checked" words. Without `jobLines` (a spec that predates the job block) the signed goal sentence is
|
|
15
21
|
* line 1 and every stage name is a check under it — `older: true`.
|
|
16
22
|
* @param {any} spec
|
|
@@ -19,8 +25,8 @@ export function checkClassOfKind(kind: unknown): "machine check" | "judge" | nul
|
|
|
19
25
|
export function planFromSpec(spec: any): JobPlan;
|
|
20
26
|
/**
|
|
21
27
|
* The plan of the confirm turn, before anything is drafted: the person's own job lines, the model's checks under the
|
|
22
|
-
* line each names, its own "not checked" words, and the real protections (code-owned) as "Always
|
|
23
|
-
* @param {{n: number, text: string, rule: string}[]|null|undefined} jobLines
|
|
28
|
+
* line each names, its own "not checked" words, and the real protections (code-owned) as "Always checked".
|
|
29
|
+
* @param {{n: number, text: string, rule: string, rules?: string[]}[]|null|undefined} jobLines
|
|
24
30
|
* @param {{checkItems?: {text: string, fromLine: number[]|null}[], checks?: string[], notChecked?: string[], protections?: string[]}} plan
|
|
25
31
|
* @returns {JobPlan}
|
|
26
32
|
*/
|
|
@@ -28,6 +34,7 @@ export function planFromConfirm(jobLines: {
|
|
|
28
34
|
n: number;
|
|
29
35
|
text: string;
|
|
30
36
|
rule: string;
|
|
37
|
+
rules?: string[];
|
|
31
38
|
}[] | null | undefined, plan: {
|
|
32
39
|
checkItems?: {
|
|
33
40
|
text: string;
|
|
@@ -45,6 +52,7 @@ export type PlanLine = {
|
|
|
45
52
|
n: number;
|
|
46
53
|
text: string;
|
|
47
54
|
rule: string;
|
|
55
|
+
rules: string[];
|
|
48
56
|
checks: PlanCheck[];
|
|
49
57
|
refused: string[];
|
|
50
58
|
};
|
package/types/panel/server.d.ts
CHANGED
|
@@ -514,10 +514,11 @@ export function getStartFromImport(id: string, opts?: {
|
|
|
514
514
|
* only `createPanelServer` below always supplies one.
|
|
515
515
|
* @param {import('node:http').IncomingMessage} req
|
|
516
516
|
* @param {import('node:http').ServerResponse} res
|
|
517
|
-
* @param {{ home?: string, port: number, token?: string, authorRoutes?: ReturnType<typeof createAuthorRoutes>, settingsRoutes?: ReturnType<typeof createSettingsRoutes>, runRoutes?: ReturnType<typeof createRunRoutes>, importRoutes?: ReturnType<typeof createImportRoutes> }} opts
|
|
517
|
+
* @param {{ home?: string, packageJsonPath?: string, port: number, token?: string, authorRoutes?: ReturnType<typeof createAuthorRoutes>, settingsRoutes?: ReturnType<typeof createSettingsRoutes>, runRoutes?: ReturnType<typeof createRunRoutes>, importRoutes?: ReturnType<typeof createImportRoutes> }} opts
|
|
518
518
|
*/
|
|
519
519
|
export function handleRequest(req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse, opts: {
|
|
520
520
|
home?: string;
|
|
521
|
+
packageJsonPath?: string;
|
|
521
522
|
port: number;
|
|
522
523
|
token?: string;
|
|
523
524
|
authorRoutes?: ReturnType<typeof createAuthorRoutes>;
|
|
@@ -544,7 +545,7 @@ export function handleRequest(req: import("node:http").IncomingMessage, res: imp
|
|
|
544
545
|
* @param {{ port?: number, home?: string, env?: Record<string,string|undefined>,
|
|
545
546
|
* sessionsRoot?: string, spawnFn?: (...a: any[]) => any, bareloopBin?: string,
|
|
546
547
|
* fetchImpl?: typeof fetch, settleMs?: number, userHome?: string,
|
|
547
|
-
* openFolderSpawn?: (cmd: string, args: string[], o: object) => any, platform?: string }} [opts]
|
|
548
|
+
* openFolderSpawn?: (cmd: string, args: string[], o: object) => any, platform?: string, packageJsonPath?: string }} [opts]
|
|
548
549
|
* @returns {Promise<{ server: import('node:http').Server, port: number, token: string, close: () => Promise<void> }>}
|
|
549
550
|
*/
|
|
550
551
|
export function createPanelServer(opts?: {
|
|
@@ -559,6 +560,7 @@ export function createPanelServer(opts?: {
|
|
|
559
560
|
userHome?: string;
|
|
560
561
|
openFolderSpawn?: (cmd: string, args: string[], o: object) => any;
|
|
561
562
|
platform?: string;
|
|
563
|
+
packageJsonPath?: string;
|
|
562
564
|
}): Promise<{
|
|
563
565
|
server: import("node:http").Server;
|
|
564
566
|
port: number;
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one statement of the step-file shape, in plain words. The worker's goal and the composer's prompt both carry it.
|
|
3
|
+
* @returns {string}
|
|
4
|
+
*/
|
|
5
|
+
export function stepFileContract(): string;
|
|
6
|
+
/**
|
|
7
|
+
* What the worker is told about each line, from the close that will grade it (PART 1b item 7): a FACTS line gets its
|
|
8
|
+
* facts and its count; a TEXT line that follows a facts line is told its numbers come from that line's quotes. Written by code from
|
|
9
|
+
* the signed parts, never by a model. A line with no rubric-step stage gets nothing here.
|
|
10
|
+
* @param {any} closeDecl @returns {{line: number, text: string}[]}
|
|
11
|
+
*/
|
|
12
|
+
export function lineBriefs(closeDecl: any): {
|
|
13
|
+
line: number;
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
/**
|
|
17
|
+
* The worker's goal for a rubric job on local files — written by code from the person's own numbered lines, never by a
|
|
18
|
+
* model. It states everything the close will judge about the FORM of the answer (the file, the keys, the quotes); what
|
|
19
|
+
* each line asks for stays in the person's own words, with its `~` rules beneath it.
|
|
20
|
+
* @param {{jobLines: {n: number, text: string, rule: string}[], files: {label: string, rel: string}[], confirmedGoal?: string|null, closeDecl?: any}} o
|
|
21
|
+
* `confirmedGoal` — the one goal sentence the person confirmed in the confirm turn, kept as the plan line
|
|
22
|
+
* `closeDecl` — the drafted close: with it, each line is briefed by what its stage checks (a facts line or a text line, `lineBriefs`)
|
|
23
|
+
* @returns {string}
|
|
24
|
+
*/
|
|
25
|
+
export function rubricGoal({ jobLines, files, confirmedGoal, closeDecl }: {
|
|
26
|
+
jobLines: {
|
|
27
|
+
n: number;
|
|
28
|
+
text: string;
|
|
29
|
+
rule: string;
|
|
30
|
+
}[];
|
|
31
|
+
files: {
|
|
32
|
+
label: string;
|
|
33
|
+
rel: string;
|
|
34
|
+
}[];
|
|
35
|
+
confirmedGoal?: string | null;
|
|
36
|
+
closeDecl?: any;
|
|
37
|
+
}): string;
|
|
38
|
+
/**
|
|
39
|
+
* The SHAPE of a `rubric-step` stage's parameters — what a part may carry — and nothing about which class is allowed in
|
|
40
|
+
* this build (that is `checkRubricParts`, which also sees the whole job). Pure, never throws.
|
|
41
|
+
* @param {unknown} p the stage's `params`
|
|
42
|
+
* @param {string} at the path prefix for reds, e.g. `stages[1].params`
|
|
43
|
+
* @returns {ShapeRed[]}
|
|
44
|
+
*/
|
|
45
|
+
export function rubricStepShapeReds(p: unknown, at: string): ShapeRed[];
|
|
46
|
+
/** the labels of the inputs a step's `cited` parts name (each once, in order) @param {any} params @returns {string[]} */
|
|
47
|
+
export function citedLabels(params: any): string[];
|
|
48
|
+
/**
|
|
49
|
+
* The rubric spec for ONE step, built from its parameters and the sha256 of each input it cites (taken from the source
|
|
50
|
+
* manifest at run start — a rubric is rebuilt per run because the inputs belong to the run, not to the signed job).
|
|
51
|
+
* `happened` is bareguard's own foundational check; the `text` floor below it stops a step file whose only key is junk
|
|
52
|
+
* from passing a rubric that has no countable part.
|
|
53
|
+
* @param {{step: number, parts: any[]}} params
|
|
54
|
+
* @param {Record<string, string>} inputShas label -> sha256 hex, for every label the step cites
|
|
55
|
+
* @returns {Record<string, any>} a spec for bareguard's `createRubric`
|
|
56
|
+
*/
|
|
57
|
+
export function buildStepSpec(params: {
|
|
58
|
+
step: number;
|
|
59
|
+
parts: any[];
|
|
60
|
+
}, inputShas: Record<string, string>): Record<string, any>;
|
|
61
|
+
/**
|
|
62
|
+
* The step file's bytes as the close reads them: the parsed JSON object, or WHY there is none. A file cut off mid-write
|
|
63
|
+
* parses to nothing (reason `not-json`); text cut off INSIDE an otherwise valid JSON object cannot be told from a short
|
|
64
|
+
* answer — that limit is documented, not hidden.
|
|
65
|
+
* @param {string|null} bytes the file's text, or null when it does not exist
|
|
66
|
+
* @returns {{obj: Record<string, any>, why: null}|{obj: null, why: 'missing'|'not-json'|'not-object'}}
|
|
67
|
+
*/
|
|
68
|
+
export function parseStepFile(bytes: string | null): {
|
|
69
|
+
obj: Record<string, any>;
|
|
70
|
+
why: null;
|
|
71
|
+
} | {
|
|
72
|
+
obj: null;
|
|
73
|
+
why: "missing" | "not-json" | "not-object";
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The step file as bareguard's rubric reads it: a flat object. `text` stays `text`; each label in `cites` becomes the field
|
|
77
|
+
* `cites:<label>` (the name a `cited` check reads its claims from). Nothing else in the file is read.
|
|
78
|
+
* @param {Record<string, any>} obj
|
|
79
|
+
* @param {string[]} [countLabels] labels whose claim COUNT a minClaims/maxClaims part reads
|
|
80
|
+
* @param {any} [factPart] the step's `fact` part: its `results` become claims (text built by code) under `cites:<source>`
|
|
81
|
+
* @returns {Record<string, any>}
|
|
82
|
+
*/
|
|
83
|
+
export function flattenStep(obj: Record<string, any>, countLabels?: string[], factPart?: any): Record<string, any>;
|
|
84
|
+
/**
|
|
85
|
+
* One bareguard gap as a sentence the worker can act on. The numbers and names are bareguard's own measurements and the
|
|
86
|
+
* person's signed limits, never anything this module infers; a gap this table does not know falls back to bareguard's own
|
|
87
|
+
* rendering, so nothing is ever dropped.
|
|
88
|
+
* @param {number} step @param {string} why why there was no object, when there was none
|
|
89
|
+
* @param {any} g a bareguard gap
|
|
90
|
+
* @param {any} [params] the stage's parameters (a fact step words its gaps by fact)
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
export function plainStepGap(step: number, why: string, g: any, params?: any): string;
|
|
94
|
+
/**
|
|
95
|
+
* Grade ONE step: build the rubric, run it over the step file's fields, and say what happened in the close's own terms.
|
|
96
|
+
* Pure of the filesystem (the runner in src/kinds.js reads the files). `stopped` = the instrument failed (never a red).
|
|
97
|
+
* @param {{params: {step: number, parts: any[]}, bytes: string|null, outputBytes: string|null, inputs: Record<string, string>,
|
|
98
|
+
* factQuotes?: Record<number, string[]>, factMissing?: number[]}} o
|
|
99
|
+
* `factQuotes` maps an earlier fact line's number to the quotes its (already checked) step file holds — what a prose step's numbers are tied to
|
|
100
|
+
* `factMissing` lists the earlier fact lines whose step file is not there (yet): a normal red, never an instrument fault
|
|
101
|
+
* `inputs` maps each cited label to its frozen TEXT; its sha256 is taken here from that text, and bareguard compares it to
|
|
102
|
+
* the manifest's recorded sha via `inputShas`.
|
|
103
|
+
* @param {Record<string, string>} inputShas the manifest's recorded sha256 per cited label
|
|
104
|
+
* @returns {Promise<{verdict: 'green'|'red'|'stopped', gapLines: string[], fault: string|null, detail: Record<string, any>}>}
|
|
105
|
+
*/
|
|
106
|
+
export function gradeStep({ params, bytes, outputBytes, inputs, factQuotes, factMissing }: {
|
|
107
|
+
params: {
|
|
108
|
+
step: number;
|
|
109
|
+
parts: any[];
|
|
110
|
+
};
|
|
111
|
+
bytes: string | null;
|
|
112
|
+
outputBytes: string | null;
|
|
113
|
+
inputs: Record<string, string>;
|
|
114
|
+
factQuotes?: Record<number, string[]>;
|
|
115
|
+
factMissing?: number[];
|
|
116
|
+
}, inputShas: Record<string, string>): Promise<{
|
|
117
|
+
verdict: "green" | "red" | "stopped";
|
|
118
|
+
gapLines: string[];
|
|
119
|
+
fault: string | null;
|
|
120
|
+
detail: Record<string, any>;
|
|
121
|
+
}>;
|
|
122
|
+
/**
|
|
123
|
+
* The labels of a job's numbered inputs, or null when it carries none (a caller that has no inputs in hand skips the label rule).
|
|
124
|
+
* @param {unknown} inputs @returns {string[]|null}
|
|
125
|
+
*/
|
|
126
|
+
export function inputLabelsOf(inputs: unknown): string[] | null;
|
|
127
|
+
/**
|
|
128
|
+
* R11 — the drafting-time rules for the `rubric-step` stages of a declaration, each a red in the person's plain words that
|
|
129
|
+
* names the job line and ends "Nothing spent." where nothing was. Pure; never throws. Judged parts are RED in this build
|
|
130
|
+
* (the judge arrives in the next one): the sorting is still asked for, so a part that needs the judge is named as such
|
|
131
|
+
* instead of being approximated by a count.
|
|
132
|
+
* - a stage serves exactly the one job line it names (`step` = its only `fromLine`), and no line has two stages;
|
|
133
|
+
* - a part with no class (`none`) cannot be counted or checked against a quote;
|
|
134
|
+
* - a `judged` part needs the judge; a `guard` part is about web sources and the job has no web input;
|
|
135
|
+
* - two countable parts of ONE line that no text can satisfy together (a minimum above a maximum) are a contradiction,
|
|
136
|
+
* naming both parts and both numbers;
|
|
137
|
+
* - a `cited` part names a label the person's inputs do not have.
|
|
138
|
+
* @param {any[]} stages the declaration's stages
|
|
139
|
+
* @param {{inputLabels?: string[]|null, red: (code: string, path: string, detail: string, extra?: object) => void}} o
|
|
140
|
+
* `inputLabels` absent = the label rule is not run (a caller with no inputs in hand)
|
|
141
|
+
*/
|
|
142
|
+
export function checkRubricParts(stages: any[], { inputLabels, red }: {
|
|
143
|
+
inputLabels?: string[] | null;
|
|
144
|
+
red: (code: string, path: string, detail: string, extra?: object) => void;
|
|
145
|
+
}): void;
|
|
146
|
+
/** the ~ rules of one job line, one string each (`rules` when the line has the array, else the joined `rule` split on "; ") @param {any} l @returns {string[]} */
|
|
147
|
+
export function lineRules(l: any): string[];
|
|
148
|
+
/**
|
|
149
|
+
* PART 1b, RF16 + RF17 — the rules that need the person's own job lines. Only a close built for REQUIRED FACTS is held to them (a
|
|
150
|
+
* close with a fact part, or any part that says which `~` rules it carries out): an older Part 1a close is left as it was signed.
|
|
151
|
+
* - every `~` rule of every job line is carried out by a part (its number in the part's `rules`), or is listed in `refused` with
|
|
152
|
+
* its `rule` number, or its whole line is refused: a rule that is none of those was silently dropped, and that is a red;
|
|
153
|
+
* - a number the AI made out of the person's words (a bound the person did not write) must be marked `aiProposal`, and a time
|
|
154
|
+
* limit the AI proposes must be a range (`between`), never one-sided — "not a red-eye" must not let a 10 PM flight through.
|
|
155
|
+
* @param {any[]} stages @param {{jobLines?: any[]|null, refused?: any, red: (code: string, path: string, detail: string, extra?: object) => void}} o
|
|
156
|
+
*/
|
|
157
|
+
export function checkRubricRules(stages: any[], { jobLines, refused, red }: {
|
|
158
|
+
jobLines?: any[] | null;
|
|
159
|
+
refused?: any;
|
|
160
|
+
red: (code: string, path: string, detail: string, extra?: object) => void;
|
|
161
|
+
}): void;
|
|
162
|
+
/**
|
|
163
|
+
* PART 1c L3 - the person's own words win over the AI's reading of them, settled by CODE before anything is validated or signed:
|
|
164
|
+
* - a limit on a fact whose bounds are all in the words the person wrote (the line, its `~` rules, an answer they gave) is the
|
|
165
|
+
* person's, so it is NOT marked "AI's proposal" (smv710w8c3wdh: the plan called the person's own range the AI's);
|
|
166
|
+
* - a time range the AI proposed while the person wrote ONE explicit positive time range ("between 07:00 and 23:00") on that line
|
|
167
|
+
* is replaced by exactly that range (smv710w8c3wdh: the plan said 5:00 AM). Only when it is unambiguous: one such range in the
|
|
168
|
+
* line's rules and one AI-proposed `between` time fact on the line; a rule with a negation ("not between ...") is never read as a range;
|
|
169
|
+
* - a `~` rule is a check or under Not checked, never both: a `refused` entry for a rule that a part of its own line carries is dropped.
|
|
170
|
+
* Pure; returns a new declaration, the input untouched. The model is told the same in the brief; this makes it true either way.
|
|
171
|
+
* @param {any} declaration @param {any[]|null|undefined} jobLines @returns {any}
|
|
172
|
+
*/
|
|
173
|
+
export function settlePersonsWords(declaration: any, jobLines: any[] | null | undefined): any;
|
|
174
|
+
/**
|
|
175
|
+
* PART 1b — put the number tie on every prose step. A rubric-step stage with no fact part that comes AFTER one or more fact
|
|
176
|
+
* stages gets exactly one `numbersFromFacts` part naming those lines; one the model wrote is replaced. Pure; returns a new
|
|
177
|
+
* declaration (the input is untouched). The model never writes this part: it is code's, so a draft cannot omit it.
|
|
178
|
+
* @param {any} declaration @returns {any}
|
|
179
|
+
*/
|
|
180
|
+
export function withFactBindings(declaration: any): any;
|
|
181
|
+
/**
|
|
182
|
+
* The ~ rules the drafter listed under Not checked (`refused` entries that name a `rule`), each as one line in the person's own
|
|
183
|
+
* words: `line N: "<the rule as written>" — <the drafter's reason>` (PART 1b, RF6 / RF16).
|
|
184
|
+
* @param {any} closeDecl @param {any[]|null|undefined} jobLines @returns {string[]}
|
|
185
|
+
*/
|
|
186
|
+
export function ruleNotChecked(closeDecl: any, jobLines: any[] | null | undefined): string[];
|
|
187
|
+
/**
|
|
188
|
+
* The Not-checked lines code owns for the rubric-step stages of a close: a prose step's CONTENT is judged by the person at
|
|
189
|
+
* Accept, and the card says so (PART 1b, RF5). One line per prose step (a stage with no fact part).
|
|
190
|
+
* @param {any} closeDecl @returns {string[]}
|
|
191
|
+
*/
|
|
192
|
+
export function proseNotChecked(closeDecl: any): string[];
|
|
193
|
+
/**
|
|
194
|
+
* One countable part as a plain sentence, written by code from the part's signed fields (never from the model's words), so the
|
|
195
|
+
* plan card and the close are one thing seen twice.
|
|
196
|
+
* @param {any} part @returns {string}
|
|
197
|
+
*/
|
|
198
|
+
export function partSentence(part: any): string;
|
|
199
|
+
/**
|
|
200
|
+
* The checks a signed close actually runs, per job line, in plain code-written sentences: one per countable part of every
|
|
201
|
+
* rubric-step stage. This is the ONE reader both the plan card and the sign-time invariant use.
|
|
202
|
+
* @param {any} closeDecl
|
|
203
|
+
* @returns {{line: number, text: string, covers: number[]}[]}
|
|
204
|
+
*/
|
|
205
|
+
export function checksOfClose(closeDecl: any): {
|
|
206
|
+
line: number;
|
|
207
|
+
text: string;
|
|
208
|
+
covers: number[];
|
|
209
|
+
}[];
|
|
210
|
+
/**
|
|
211
|
+
* Reconcile the CONFIRMED plan with the close the composer actually wrote. The plan card after drafting shows exactly
|
|
212
|
+
* the close's own checks (`checksOfClose`); every confirmed check that no part carries out (no part lists its number in
|
|
213
|
+
* `covers`) is moved to Not checked, in the person's words, with the reason. A check can therefore never be shown and then
|
|
214
|
+
* silently dropped (run mv5bk400: "lists 3 releases" was confirmed, then left out of the signed close without a word).
|
|
215
|
+
* @param {{confirmed: {text: string, fromLine: number[]|null}[], notChecked: string[], closeDecl: any, jobLines?: any[]|null}} o
|
|
216
|
+
* `jobLines` — the person's numbered lines, so a ~ rule the drafter listed as Not checked reads in the person's own words
|
|
217
|
+
* @returns {{checkItems: {text: string, fromLine: number[]}[], notChecked: string[], moved: {text: string, fromLine: number[]|null}[]}}
|
|
218
|
+
*/
|
|
219
|
+
export function reconcileRubricPlan({ confirmed, notChecked, closeDecl, jobLines }: {
|
|
220
|
+
confirmed: {
|
|
221
|
+
text: string;
|
|
222
|
+
fromLine: number[] | null;
|
|
223
|
+
}[];
|
|
224
|
+
notChecked: string[];
|
|
225
|
+
closeDecl: any;
|
|
226
|
+
jobLines?: any[] | null;
|
|
227
|
+
}): {
|
|
228
|
+
checkItems: {
|
|
229
|
+
text: string;
|
|
230
|
+
fromLine: number[];
|
|
231
|
+
}[];
|
|
232
|
+
notChecked: string[];
|
|
233
|
+
moved: {
|
|
234
|
+
text: string;
|
|
235
|
+
fromLine: number[] | null;
|
|
236
|
+
}[];
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* The sign-time invariant: the checks the person was shown (`shown`, from the plan card) are exactly the checks the signed
|
|
240
|
+
* close runs (`checksOfClose`), per line. Pure.
|
|
241
|
+
* @param {{text: string, fromLine: number[]|null}[]} shown @param {any} closeDecl
|
|
242
|
+
* @returns {{ok: true}|{ok: false, error: string}}
|
|
243
|
+
*/
|
|
244
|
+
export function planMatchesClose(shown: {
|
|
245
|
+
text: string;
|
|
246
|
+
fromLine: number[] | null;
|
|
247
|
+
}[], closeDecl: any): {
|
|
248
|
+
ok: true;
|
|
249
|
+
} | {
|
|
250
|
+
ok: false;
|
|
251
|
+
error: string;
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* The frozen TEXT of the named inputs, read the way the runner reads them: the source door's record (`source.json`, one level
|
|
255
|
+
* above the tree) names each input's file and sha256, and a file whose bytes no longer match is not returned. Used at DRAFTING
|
|
256
|
+
* (the drafter reads the input, the early tests run on it) and at run start (the backstop). Never throws.
|
|
257
|
+
* @param {string} workdir the frozen tree @param {string[]} labels
|
|
258
|
+
* @returns {Promise<{ok: true, texts: Record<string, string>}|{ok: false, why: string}>}
|
|
259
|
+
*/
|
|
260
|
+
export function readFrozenInputs(workdir: string, labels: string[]): Promise<{
|
|
261
|
+
ok: true;
|
|
262
|
+
texts: Record<string, string>;
|
|
263
|
+
} | {
|
|
264
|
+
ok: false;
|
|
265
|
+
why: string;
|
|
266
|
+
}>;
|
|
267
|
+
/** where the per-line step files live, inside the job's tree; `copyOut` delivers them with the rest of `output/` */
|
|
268
|
+
export const STEP_DIR: "output/steps";
|
|
269
|
+
export function stepFileRel(n: number): string;
|
|
270
|
+
/** the largest step file the close reads: a bigger one is a stop, never silently truncated (bareguard's own source cap) */
|
|
271
|
+
export const STEP_MAX_BYTES: number;
|
|
272
|
+
/** the closed set of classes a part is sorted into; `none` = "I could not sort this one" (a red, in plain words, never a guess) */
|
|
273
|
+
export const PART_CLASSES: readonly string[];
|
|
274
|
+
/**
|
|
275
|
+
* The counted/quoted checks a `countable` part may name, with the fields each needs — read off bareguard's own rule table
|
|
276
|
+
* (`rubricVocabulary`): the names are bareguard's, so a check this build cannot run is inexpressible, not rejected late.
|
|
277
|
+
* (`max`/`min` need a numeric field the step file does not have, so they are not offered.)
|
|
278
|
+
* @type {Readonly<Record<string, readonly string[]>>}
|
|
279
|
+
*/
|
|
280
|
+
export const COUNT_CHECKS: Readonly<Record<string, readonly string[]>>;
|
|
281
|
+
export function sha256Of(b: string | Buffer): string;
|
|
282
|
+
export type ShapeRed = {
|
|
283
|
+
code: string;
|
|
284
|
+
path: string;
|
|
285
|
+
detail: string;
|
|
286
|
+
};
|
package/types/source.d.ts
CHANGED
|
@@ -330,6 +330,100 @@ export function proveInputFiles(inputs: {
|
|
|
330
330
|
ok: false;
|
|
331
331
|
error: string;
|
|
332
332
|
}>;
|
|
333
|
+
/**
|
|
334
|
+
* Does this source manifest belong to a rubric job on local files (`proveRubricInputs` wrote it)? One spelling for both
|
|
335
|
+
* doors (the panel session and the CLI author run): a non-repo source that froze numbered, labelled input files.
|
|
336
|
+
* @param {Record<string, any>|null|undefined} manifest
|
|
337
|
+
* @returns {boolean}
|
|
338
|
+
*/
|
|
339
|
+
export function isRubricFilesManifest(manifest: Record<string, any> | null | undefined): boolean;
|
|
340
|
+
/**
|
|
341
|
+
* PART 1a (docs/product/ITEM33-BUILD.md, "Addendum 2026-10-12"): the front door for a RUBRIC job whose inputs are the
|
|
342
|
+
* person's own LOCAL FILES, not a repo. Each numbered `label: /absolute/file` line is proven at $0 and frozen into the
|
|
343
|
+
* same hidden-git tree a plain folder gets (`prepareSource`, which also refuses a secret shape, an environment file
|
|
344
|
+
* and a symlink), under `input/`; the manifest then also records `inputs: [{label, rel, sha256}]` — the bytes the
|
|
345
|
+
* rubric's `cited` check will search a quote in, hashed once, here. A line that is a web address is fetched ONCE with
|
|
346
|
+
* barebrowse (PART 1c, read only) and its text frozen under `input/` like a file (the manifest row also records its `url`,
|
|
347
|
+
* so run start can fetch it again); a `search:` line is a named refusal (a later build); so is a relative path, a missing file, a folder, a file over
|
|
348
|
+
* {@link RUBRIC_INPUT_MAX_BYTES}, and text that is not valid UTF-8. Every refusal is plain words naming the line and
|
|
349
|
+
* ends "Nothing spent." — nothing here touches a model.
|
|
350
|
+
* @param {{inputs: {n: number, label: string, value: string}[], into: string, destination?: string, fetchUrl?: (url: string) => Promise<{ok: true, text: string, url: string}|{ok: false, error: string}>}} o `fetchUrl` - how a web address is read (default barebrowse via `fetchPageText`; a test injects a stub, never the network)
|
|
351
|
+
* @returns {Promise<{ok: true, prep: {stop: null, into: string, tree: string, manifestPath: string, manifest: Record<string, any>}}|{ok: false, error: string, code: string}>}
|
|
352
|
+
*/
|
|
353
|
+
export function proveRubricInputs({ inputs, into, destination, fetchUrl }: {
|
|
354
|
+
inputs: {
|
|
355
|
+
n: number;
|
|
356
|
+
label: string;
|
|
357
|
+
value: string;
|
|
358
|
+
}[];
|
|
359
|
+
into: string;
|
|
360
|
+
destination?: string;
|
|
361
|
+
fetchUrl?: (url: string) => Promise<{
|
|
362
|
+
ok: true;
|
|
363
|
+
text: string;
|
|
364
|
+
url: string;
|
|
365
|
+
} | {
|
|
366
|
+
ok: false;
|
|
367
|
+
error: string;
|
|
368
|
+
}>;
|
|
369
|
+
}): Promise<{
|
|
370
|
+
ok: true;
|
|
371
|
+
prep: {
|
|
372
|
+
stop: null;
|
|
373
|
+
into: string;
|
|
374
|
+
tree: string;
|
|
375
|
+
manifestPath: string;
|
|
376
|
+
manifest: Record<string, any>;
|
|
377
|
+
};
|
|
378
|
+
} | {
|
|
379
|
+
ok: false;
|
|
380
|
+
error: string;
|
|
381
|
+
code: string;
|
|
382
|
+
}>;
|
|
383
|
+
/**
|
|
384
|
+
* Is this Inputs value a path to an existing regular FILE on this machine (not a repo folder, not a web address, not a
|
|
385
|
+
* missing path)? The $0 peek that tells a rubric job on local files from a rubric job on a repo before a session exists;
|
|
386
|
+
* `proveRubricInputs` makes the authoritative, line-by-line proof.
|
|
387
|
+
* @param {string} value
|
|
388
|
+
* @returns {boolean}
|
|
389
|
+
*/
|
|
390
|
+
export function looksLikeLocalFile(value: string): boolean;
|
|
391
|
+
/**
|
|
392
|
+
* Is this Inputs value one a rubric job can work on without a repo: a regular FILE on this machine, or a web address (PART 1c)?
|
|
393
|
+
* @param {string} value
|
|
394
|
+
* @returns {boolean}
|
|
395
|
+
*/
|
|
396
|
+
export function looksLikeRubricInput(value: string): boolean;
|
|
397
|
+
/**
|
|
398
|
+
* RUN START for a rubric job with web inputs (PART 1c, RF22): fetch every web input AGAIN and make that text the run's frozen input
|
|
399
|
+
* BEFORE the worker starts. The drafting copy was only for the look (prices change); the close grades, and the worker reads, THIS
|
|
400
|
+
* copy. It is written into the prepared tree, committed as the new seed (so the page is never read as a worker write), and
|
|
401
|
+
* `source.json` is rewritten (new sha256 per input, new seed, `draftSha256` keeps what the look saw). Nothing but the text of a
|
|
402
|
+
* recorded web address is ever refetched; a job with only file inputs returns at once and changes nothing.
|
|
403
|
+
* @param {{into: string, fetchUrl?: (url: string) => Promise<{ok: true, text: string, url: string}|{ok: false, error: string}>}} o `into` - the prepared copy (source.json + tree/)
|
|
404
|
+
* @returns {Promise<{ok: true, refreshed: string[], seed: string|null}|{ok: false, error: string}>}
|
|
405
|
+
*/
|
|
406
|
+
export function refreezeUrlInputs({ into, fetchUrl }: {
|
|
407
|
+
into: string;
|
|
408
|
+
fetchUrl?: (url: string) => Promise<{
|
|
409
|
+
ok: true;
|
|
410
|
+
text: string;
|
|
411
|
+
url: string;
|
|
412
|
+
} | {
|
|
413
|
+
ok: false;
|
|
414
|
+
error: string;
|
|
415
|
+
}>;
|
|
416
|
+
}): Promise<{
|
|
417
|
+
ok: true;
|
|
418
|
+
refreshed: string[];
|
|
419
|
+
seed: string | null;
|
|
420
|
+
} | {
|
|
421
|
+
ok: false;
|
|
422
|
+
error: string;
|
|
423
|
+
}>;
|
|
424
|
+
/** the per-file ceiling for a rubric input: bareguard's `cited` check searches a quote in a source only up to this size
|
|
425
|
+
* (its `quoteSourceMaxBytes`); a bigger file could never be cited from, so the door refuses it at $0 */
|
|
426
|
+
export const RUBRIC_INPUT_MAX_BYTES: number;
|
|
333
427
|
/**
|
|
334
428
|
* a named, non-throwing stop
|
|
335
429
|
*/
|
package/types/userrun.d.ts
CHANGED
|
@@ -61,6 +61,17 @@ export type Deps = {
|
|
|
61
61
|
*/
|
|
62
62
|
provider?: any;
|
|
63
63
|
providerFor?: ((tier: string) => any) | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* PART 1c - a test seam: how a web input is read at run start (production: barebrowse)
|
|
66
|
+
*/
|
|
67
|
+
fetchUrl?: ((url: string) => Promise<{
|
|
68
|
+
ok: true;
|
|
69
|
+
text: string;
|
|
70
|
+
url: string;
|
|
71
|
+
} | {
|
|
72
|
+
ok: false;
|
|
73
|
+
error: string;
|
|
74
|
+
}>) | undefined;
|
|
64
75
|
judgeProvider?: any;
|
|
65
76
|
/**
|
|
66
77
|
* F196 — a test seam for `appendRun`'s
|