@openmixer/plugin-qualify 0.18.0 → 0.18.2

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.
Files changed (73) hide show
  1. package/README.md +93 -3
  2. package/bin/plugin-qualify-sync.mjs +3 -1
  3. package/dist/clap-qualify.d.ts +3 -1
  4. package/dist/clap-qualify.js +3 -1
  5. package/dist/clap-qualify.js.map +1 -1
  6. package/dist/distributed-records.d.ts +4 -2
  7. package/dist/distributed-records.js +1 -1
  8. package/dist/distributed-records.js.map +1 -1
  9. package/dist/host-admission.d.ts +21 -0
  10. package/dist/host-admission.js +33 -3
  11. package/dist/host-admission.js.map +1 -1
  12. package/dist/hostd-pin-files.js +3 -1
  13. package/dist/hostd-pin-files.js.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +2 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/measurement/format.d.ts +10 -0
  18. package/dist/measurement/format.js +8 -0
  19. package/dist/measurement/format.js.map +1 -1
  20. package/dist/measurement/probe-json.js +2 -1
  21. package/dist/measurement/probe-json.js.map +1 -1
  22. package/dist/probe-judge.d.ts +11 -0
  23. package/dist/probe-judge.js +6 -3
  24. package/dist/probe-judge.js.map +1 -1
  25. package/dist/probe-runner.js +3 -2
  26. package/dist/probe-runner.js.map +1 -1
  27. package/dist/qualification-record.d.ts +113 -8
  28. package/dist/qualification-record.js +18 -13
  29. package/dist/qualification-record.js.map +1 -1
  30. package/dist/qualify-adapter-pass.d.ts +67 -0
  31. package/dist/qualify-adapter-pass.js +255 -0
  32. package/dist/qualify-adapter-pass.js.map +1 -0
  33. package/dist/qualify-declarations.d.ts +30 -0
  34. package/dist/qualify-declarations.js +24 -1
  35. package/dist/qualify-declarations.js.map +1 -1
  36. package/dist/qualify-isolated.d.ts +70 -0
  37. package/dist/qualify-isolated.js +184 -0
  38. package/dist/qualify-isolated.js.map +1 -0
  39. package/dist/qualify-rejudge.d.ts +82 -0
  40. package/dist/qualify-rejudge.js +434 -0
  41. package/dist/qualify-rejudge.js.map +1 -0
  42. package/dist/qualify-sync.d.ts +97 -1
  43. package/dist/qualify-sync.js +276 -24
  44. package/dist/qualify-sync.js.map +1 -1
  45. package/fixtures/records-0.16.1/http___example.org_raffo@unversioned-2060c09ff626.default.probe.json +46 -0
  46. package/fixtures/records-0.16.1/http___example.org_raffo@unversioned-2060c09ff626.default.qualification.json +185 -0
  47. package/fixtures/records-0.16.1/http___lv2plug.in_plugins_eg-amp@unversioned-f046a60efd45.default.probe.json +51 -0
  48. package/fixtures/records-0.16.1/http___lv2plug.in_plugins_eg-amp@unversioned-f046a60efd45.default.qualification.json +232 -0
  49. package/fixtures/records-0.16.1/https___github.com_lucianodato_noise-repellent@unversioned-c3b5e21dd9a7.default.probe.json +51 -0
  50. package/fixtures/records-0.16.1/https___github.com_lucianodato_noise-repellent@unversioned-c3b5e21dd9a7.default.qualification.json +245 -0
  51. package/fixtures/records-0.16.1/in.lsp-plug.impulse_responses_mono@unversioned-d5235d2f5f53.custom.probe.json +52 -0
  52. package/fixtures/records-0.16.1/in.lsp-plug.impulse_responses_mono@unversioned-d5235d2f5f53.custom.qualification.json +145 -0
  53. package/fixtures/records-0.16.1/in.lsp-plug.trigger_midi_mono@unversioned-d5235d2f5f53.custom.probe.json +52 -0
  54. package/fixtures/records-0.16.1/in.lsp-plug.trigger_midi_mono@unversioned-d5235d2f5f53.custom.qualification.json +155 -0
  55. package/package.json +1 -1
  56. package/src/clap-qualify.ts +5 -1
  57. package/src/distributed-records.ts +1 -1
  58. package/src/host-admission.ts +40 -3
  59. package/src/hostd-pin-files.ts +3 -1
  60. package/src/index.ts +2 -0
  61. package/src/measurement/format.ts +17 -0
  62. package/src/measurement/probe-json.ts +2 -1
  63. package/src/probe-judge.ts +10 -3
  64. package/src/probe-runner.ts +2 -2
  65. package/src/qualification-record.ts +126 -15
  66. package/src/qualify-adapter-pass.ts +278 -0
  67. package/src/qualify-declarations.ts +26 -1
  68. package/src/qualify-isolated.ts +201 -0
  69. package/src/qualify-rejudge.ts +466 -0
  70. package/src/qualify-sync.ts +295 -24
  71. package/tools/isolated-step.mjs +122 -0
  72. package/tools/lv2_resolve.py +49 -0
  73. package/tools/mod-host-admit.mjs +99 -7
@@ -0,0 +1,70 @@
1
+ import { type JackStarter } from "./qualify-adapter-pass.js";
2
+ import type { GridCell } from "./measurement-grid.js";
3
+ import type { PinEntry } from "./pins-file.js";
4
+ import type { QualificationRecord, RunStep } from "./qualification-record.js";
5
+ /** The steps of a pass, in the order they run. */
6
+ export declare const RUN_STEP: {
7
+ readonly scan: "scan";
8
+ readonly describe: "describe";
9
+ readonly probe: "probe";
10
+ readonly rtSafety: "rt-safety";
11
+ readonly isolated: "isolated";
12
+ };
13
+ export declare const ISOLATED_RESULT: {
14
+ readonly isolated: "isolated";
15
+ readonly refused: "refused";
16
+ readonly notRun: "not-run";
17
+ };
18
+ /** Why the step refused a plugin, or why it could not run. */
19
+ export declare const ISOLATED_CODE: {
20
+ readonly crashed: "isolated.crashed";
21
+ readonly notAdded: "isolated.not-added";
22
+ readonly noWorker: "isolated.no-worker";
23
+ readonly notAlone: "isolated.not-alone";
24
+ readonly nonFinite: "isolated.non-finite-output";
25
+ readonly silent: "isolated.silent-output";
26
+ readonly noServer: "isolated.no-private-server";
27
+ readonly noHost: "isolated.no-host";
28
+ };
29
+ /** What one run of the step saw. A run that never reached the plugin says `started: false`, and `problem`. */
30
+ export interface IsolatedRunFacts {
31
+ readonly started: boolean;
32
+ readonly problem?: string;
33
+ readonly added?: boolean;
34
+ /** How many workers `worker_list` showed, and how many instances the plugin's holds. */
35
+ readonly workers?: number;
36
+ readonly instancesInWorker?: number;
37
+ readonly alive?: boolean;
38
+ readonly latencyFrames?: number;
39
+ readonly cpuPercent?: number;
40
+ readonly xruns?: number;
41
+ readonly finite?: boolean;
42
+ readonly silent?: boolean;
43
+ }
44
+ export type IsolatedRunner = (uri: string, cell: GridCell, env: Readonly<Record<string, string | undefined>>) => IsolatedRunFacts;
45
+ /** The decision table of the step, with the figures it took. Pure. */
46
+ export declare function judgeIsolatedRun(run: IsolatedRunFacts): RunStep;
47
+ /** Whether a record's outcome calls for the isolated step: rated `conditional` by some host, or a probe that crashed or hung. */
48
+ export declare function owesIsolated(record: QualificationRecord): boolean;
49
+ /** Whether the isolated step saw this plugin running alone. A record's word alone never says so. */
50
+ export declare function provenAlone(record: QualificationRecord): boolean;
51
+ /** The steps a record's outcome calls for. */
52
+ export declare function stepsCalledFor(record: QualificationRecord): readonly string[];
53
+ /** The steps a record that carries a `run` lacks, for the sync to refuse it by. A record from before the steps has none to lack. */
54
+ export declare function missingSteps(record: QualificationRecord): readonly string[];
55
+ /** The steps every record has by the time it is written, from what it says of them. Pure. */
56
+ export declare function baseSteps(record: QualificationRecord, describeProblem?: string): RunStep[];
57
+ /** The step as it runs on a device: a private server at the cell, and `tools/isolated-step.mjs` under it. */
58
+ export declare function spawnedIsolatedRunner(jack?: JackStarter): IsolatedRunner;
59
+ /** The cell the step runs at: the rate and quantum the host's cost was judged at, else the first cell a Pi runs. */
60
+ export declare function isolatedCell(record: QualificationRecord, host: string): GridCell;
61
+ /** The pin once the step has spoken: its verdict word follows the step, and a step that could not run leaves none. Pure. */
62
+ export declare function pinAfterStep(pin: PinEntry | undefined, step: RunStep): PinEntry | undefined;
63
+ /**
64
+ * The missing isolated step of a record already judged: the run keeps its id and gains the step, and nothing else is
65
+ * measured. `undefined` when it owes none, or has no run id to extend. Writes the record whole.
66
+ */
67
+ export declare function completeIsolated(path: string, record: QualificationRecord, uri: string, cell: GridCell, runner: IsolatedRunner, env: Readonly<Record<string, string | undefined>>): {
68
+ readonly record: QualificationRecord;
69
+ readonly step: RunStep;
70
+ } | undefined;
@@ -0,0 +1,184 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
3
+ /**
4
+ * The steps of one plugin's pass, and the last of them: `verdict=isolated` means the plugin was seen running alone in a
5
+ * worker of its own (plugin-qualify#249). A plugin the RT-safety step finds unsafe takes the isolated step in the same
6
+ * pass, and so does one that crashed or hung in the probe. The step runs on a private JACK server at the host's rate and
7
+ * quantum, under a plugin-hostd of its own: the plugin is added alone, `worker_list` must show it alone, and a sine plays
8
+ * through it for a window. Only a plugin that was added, stayed alive and gave finite, non-silent output is isolated. A
9
+ * machine that could not run the step decides nothing about the plugin: no verdict word, and the sync tries it again.
10
+ *
11
+ * Every record says which steps judged it. {@link missingSteps} is what the sync refuses a record by; a record from before
12
+ * the steps has no `run` at all, owes the isolated step if its outcome calls for one, and a completion adds it
13
+ * ({@link completeIsolated}), measuring nothing else.
14
+ */
15
+ import { spawnSync } from "node:child_process";
16
+ import { existsSync, readFileSync } from "node:fs";
17
+ import { basename, join } from "node:path";
18
+ import { ADAPTER_PASS_CELLS, startPrivateJack } from "./qualify-adapter-pass.js";
19
+ import { PROBE_OK, readProbeOutput } from "./probe-output.js";
20
+ import { ISOLATED_SIGNAL_TOOL_ENV, ISOLATED_SIGNAL_TOOL_NAME } from "./qualify-declarations.js";
21
+ import { locateNativeTool, toolsDir } from "./tool-paths.js";
22
+ import { writeFileWhole } from "./whole-file.js";
23
+ /** The steps of a pass, in the order they run. */
24
+ export const RUN_STEP = { scan: "scan", describe: "describe", probe: "probe", rtSafety: "rt-safety", isolated: "isolated" };
25
+ export const ISOLATED_RESULT = { isolated: "isolated", refused: "refused", notRun: "not-run" };
26
+ /** Why the step refused a plugin, or why it could not run. */
27
+ export const ISOLATED_CODE = {
28
+ crashed: "isolated.crashed",
29
+ notAdded: "isolated.not-added",
30
+ noWorker: "isolated.no-worker",
31
+ notAlone: "isolated.not-alone",
32
+ nonFinite: "isolated.non-finite-output",
33
+ silent: "isolated.silent-output",
34
+ noServer: "isolated.no-private-server",
35
+ noHost: "isolated.no-host",
36
+ };
37
+ /** The outcomes of a probe that take the isolated step as well: the plugin never reached a verdict in-process. */
38
+ const PROBE_FAILED_HARD = new Set(["probe.crashed", "probe.timeout"]);
39
+ /** The decision table of the step, with the figures it took. Pure. */
40
+ export function judgeIsolatedRun(run) {
41
+ const step = (result, code, detail) => ({
42
+ step: RUN_STEP.isolated,
43
+ result,
44
+ ...(code === undefined ? {} : { code }),
45
+ ...(detail === undefined ? {} : { detail }),
46
+ ...(figuresOf(run) === undefined ? {} : { figures: figuresOf(run) }),
47
+ });
48
+ if (!run.started)
49
+ return step(ISOLATED_RESULT.notRun, ISOLATED_CODE.noHost, run.problem);
50
+ if (run.added !== true)
51
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.notAdded, run.problem);
52
+ if (run.alive !== true)
53
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.crashed, run.problem);
54
+ if ((run.workers ?? 0) < 1)
55
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.noWorker);
56
+ if (run.workers !== 1 || run.instancesInWorker !== 1)
57
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.notAlone);
58
+ if (run.finite !== true)
59
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.nonFinite);
60
+ if (run.silent !== false)
61
+ return step(ISOLATED_RESULT.refused, ISOLATED_CODE.silent);
62
+ return step(ISOLATED_RESULT.isolated);
63
+ }
64
+ function figuresOf(run) {
65
+ if (run.latencyFrames === undefined && run.cpuPercent === undefined && run.xruns === undefined)
66
+ return undefined;
67
+ return {
68
+ ...(run.latencyFrames === undefined ? {} : { latencyFrames: run.latencyFrames }),
69
+ ...(run.cpuPercent === undefined ? {} : { cpuPercent: run.cpuPercent }),
70
+ ...(run.xruns === undefined ? {} : { xruns: run.xruns }),
71
+ };
72
+ }
73
+ /** Whether a record's outcome calls for the isolated step: rated `conditional` by some host, or a probe that crashed or hung. */
74
+ export function owesIsolated(record) {
75
+ return PROBE_FAILED_HARD.has(record.probe.outcome) || record.verdicts.some((v) => v.measured && v.rating === "conditional");
76
+ }
77
+ /** Whether the isolated step saw this plugin running alone. A record's word alone never says so. */
78
+ export function provenAlone(record) {
79
+ return record.run?.steps.some((s) => s.step === RUN_STEP.isolated && s.result === ISOLATED_RESULT.isolated) === true;
80
+ }
81
+ /** The steps a record's outcome calls for. */
82
+ export function stepsCalledFor(record) {
83
+ return [
84
+ RUN_STEP.scan,
85
+ RUN_STEP.describe,
86
+ RUN_STEP.probe,
87
+ ...(record.probe.outcome === PROBE_OK ? [RUN_STEP.rtSafety] : []),
88
+ ...(owesIsolated(record) ? [RUN_STEP.isolated] : []),
89
+ ];
90
+ }
91
+ /** The steps a record that carries a `run` lacks, for the sync to refuse it by. A record from before the steps has none to lack. */
92
+ export function missingSteps(record) {
93
+ if (record.run === undefined)
94
+ return [];
95
+ const had = new Set(record.run.steps.map((s) => s.step));
96
+ return stepsCalledFor(record).filter((s) => !had.has(s));
97
+ }
98
+ /** The steps every record has by the time it is written, from what it says of them. Pure. */
99
+ export function baseSteps(record, describeProblem) {
100
+ const measured = record.measurements.grid.some((p) => p.rtSafety !== undefined);
101
+ return [
102
+ { step: RUN_STEP.scan, result: "ok" },
103
+ describeProblem === undefined ? { step: RUN_STEP.describe, result: "ok" } : { step: RUN_STEP.describe, result: "failed", detail: describeProblem },
104
+ { step: RUN_STEP.probe, result: record.probe.outcome },
105
+ ...(record.probe.outcome === PROBE_OK
106
+ ? [{ step: RUN_STEP.rtSafety, result: !measured ? "not-measured" : record.verdicts.some((v) => v.rating === "conditional") ? "unsafe" : "safe" }]
107
+ : []),
108
+ ];
109
+ }
110
+ /** How long the sine plays, and what a step may take beyond it: the host's start and its answers. */
111
+ const ISOLATED_WINDOW_MS = 3000;
112
+ const ISOLATED_STEP_SLACK_MS = 90000;
113
+ /** The step as it runs on a device: a private server at the cell, and `tools/isolated-step.mjs` under it. */
114
+ export function spawnedIsolatedRunner(jack = startPrivateJack) {
115
+ return (uri, cell, env) => {
116
+ const signal = locateNativeTool(ISOLATED_SIGNAL_TOOL_NAME, env, existsSync).path;
117
+ if (signal === undefined)
118
+ return { started: false, problem: `no ${ISOLATED_SIGNAL_TOOL_NAME}` };
119
+ const server = jack(cell);
120
+ if (server === undefined)
121
+ return { started: false, problem: `${ISOLATED_CODE.noServer} at ${String(cell.rate)}/${String(cell.quantum)}` };
122
+ try {
123
+ const r = spawnSync(process.execPath, [join(toolsDir(), "isolated-step.mjs"), uri, String(ISOLATED_WINDOW_MS)], {
124
+ encoding: "utf8",
125
+ timeout: ISOLATED_WINDOW_MS + ISOLATED_STEP_SLACK_MS,
126
+ killSignal: "SIGKILL",
127
+ env: { ...env, JACK_DEFAULT_SERVER: server.name, [ISOLATED_SIGNAL_TOOL_ENV]: signal },
128
+ });
129
+ if (r.error !== undefined || r.status !== 0)
130
+ return { started: false, problem: `isolated-step: ${r.error?.message ?? `exit ${String(r.status)}`}: ${(r.stderr ?? "").trim()}` };
131
+ return JSON.parse(r.stdout);
132
+ }
133
+ finally {
134
+ server.stop();
135
+ }
136
+ };
137
+ }
138
+ /** The cell the step runs at: the rate and quantum the host's cost was judged at, else the first cell a Pi runs. */
139
+ export function isolatedCell(record, host) {
140
+ const at = record.cost.find((c) => c.host === host) ?? record.cost[0];
141
+ return at === undefined ? ADAPTER_PASS_CELLS[0] : { rate: at.rate, quantum: at.quantum };
142
+ }
143
+ /** The pin once the step has spoken: its verdict word follows the step, and a step that could not run leaves none. Pure. */
144
+ export function pinAfterStep(pin, step) {
145
+ if (pin === undefined)
146
+ return undefined;
147
+ const { verdict: _had, ...rest } = pin;
148
+ if (step.result === ISOLATED_RESULT.isolated)
149
+ return { ...rest, verdict: "isolated" };
150
+ if (step.result === ISOLATED_RESULT.refused)
151
+ return { ...rest, verdict: "refused" };
152
+ return rest;
153
+ }
154
+ /** The run id of a record from before the steps: its probe output's, read from the copy beside it. */
155
+ function runIdOf(record, dir) {
156
+ if (record.run !== undefined)
157
+ return record.run.id;
158
+ if (record.rejudged !== undefined)
159
+ return record.rejudged.figures.runId;
160
+ try {
161
+ const read = readProbeOutput(readFileSync(join(dir, basename(record.probe.file)), "utf8"));
162
+ return read.ok ? read.output.run.id : undefined;
163
+ }
164
+ catch {
165
+ return undefined;
166
+ }
167
+ }
168
+ /**
169
+ * The missing isolated step of a record already judged: the run keeps its id and gains the step, and nothing else is
170
+ * measured. `undefined` when it owes none, or has no run id to extend. Writes the record whole.
171
+ */
172
+ export function completeIsolated(path, record, uri, cell, runner, env) {
173
+ if (!owesIsolated(record) || record.run?.steps.some((s) => s.step === RUN_STEP.isolated) === true)
174
+ return undefined;
175
+ const id = runIdOf(record, join(path, ".."));
176
+ if (id === undefined)
177
+ return undefined;
178
+ const step = judgeIsolatedRun(runner(uri, cell, env));
179
+ const run = { id, steps: [...(record.run?.steps ?? baseSteps(record)), step] };
180
+ const next = { ...record, run };
181
+ writeFileWhole(path, `${JSON.stringify(next, null, 2)}\n`);
182
+ return { record: next, step };
183
+ }
184
+ //# sourceMappingURL=qualify-isolated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qualify-isolated.js","sourceRoot":"","sources":["../src/qualify-isolated.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { type GridCell } from "./measurement-grid.js";
2
+ import { type ProbeOutput } from "./probe-output.js";
3
+ import { type ProbeRun } from "./probe-runner.js";
4
+ import { type NotMeasured, type OwedMeasurement, type QualificationRecord } from "./qualification-record.js";
5
+ import { type SyncContext, type SyncState } from "./qualify-sync.js";
6
+ /** The codes of a measurement a record owes. */
7
+ export declare const OWED_CODE: {
8
+ readonly isolatedStep: "qualify.sync.isolated-step-owed";
9
+ /** An LV2 verdict of a host that runs it through the adapter, and no measured adapter run. */
10
+ readonly adapterRun: "qualify.sync.adapter-run-owed";
11
+ /** A verdict decided by a run under its host (mod-host, jalv), and no run in the record. */
12
+ readonly hostRun: "qualify.sync.host-run-owed";
13
+ /** The plugin's files are not the bytes the record measured. */
14
+ readonly bytesChanged: "qualify.sync.bytes-changed";
15
+ /** The probe output is missing, is not the copy the record names, or does not read. */
16
+ readonly figuresUnreadable: "qualify.sync.figures-unreadable";
17
+ /** The plugin has a record that holds no figures at all. */
18
+ readonly noFigures: "qualify.sync.no-figures";
19
+ };
20
+ /** The cells the memory-only pass measures: the ones a Pi runs, 48 kHz at 128 and 256 frames. */
21
+ export declare const MEMORY_PASS_CELLS: readonly GridCell[];
22
+ /** What a memory-only pass cannot say, in every record it writes to: growth over time needs a soak. */
23
+ export declare const MEMORY_PASS_NOT_MEASURED: NotMeasured;
24
+ /** The tool as the record says it: this package's own version, read where it is installed. */
25
+ export declare function rejudgeToolName(): string;
26
+ /** A world holding one bundle, as plugin-hostd runs a pinned LV2 plugin, for as long as `body` runs. */
27
+ export declare function lv2World<T>(bundle: string, body: (world: string) => T): T;
28
+ export declare class RejudgeRefusal extends Error {
29
+ }
30
+ /**
31
+ * One record judged again from its probe output, with what it owes. The figures, who took them and when are as they were;
32
+ * only the verdicts, the tiers and the cost reasons beside them are new. `at` is the prior re-judge's when nothing else
33
+ * differs, so that a second run leaves the file alone.
34
+ */
35
+ export declare function rejudgeRecord(record: QualificationRecord, probeBytes: Uint8Array, options: {
36
+ readonly host: string;
37
+ readonly by: string;
38
+ readonly at: string;
39
+ }): {
40
+ record: QualificationRecord;
41
+ owes: readonly OwedMeasurement[];
42
+ };
43
+ /** The file that lists what a re-judge left owing, beside the state file. */
44
+ export declare const owedFile: (stateFile: string) => string;
45
+ export declare const OWED_SCHEMA = "plugin-qualify.owed/1";
46
+ export interface OwingRecord {
47
+ readonly plugin: string;
48
+ /** The record's file name, when the plugin has one. */
49
+ readonly record?: string;
50
+ readonly owes: readonly OwedMeasurement[];
51
+ }
52
+ export interface RejudgeResult {
53
+ readonly state: SyncState;
54
+ readonly changed: number;
55
+ readonly unchanged: number;
56
+ readonly owing: readonly OwingRecord[];
57
+ }
58
+ /**
59
+ * Every record of the device's qualification directory judged again, the state's outcomes and pin words brought into line,
60
+ * and the list of what is owed written beside the state file. Each file is written whole, and only when it differs.
61
+ */
62
+ export declare function rejudgeState(ctx: SyncContext, state: SyncState, now?: () => string): RejudgeResult;
63
+ /**
64
+ * A memory-only run's footprints in a record: the `memory` of each cell and nothing else of it, a cell the record's grid
65
+ * does not hold joined with no other figure. A cell the run could not read says why instead of a figure, so that it is
66
+ * never read as fitting. Pure.
67
+ */
68
+ export declare function mergeMemoryRun(record: QualificationRecord, output: ProbeOutput, cells: readonly GridCell[]): QualificationRecord;
69
+ export interface MemoryPassResult {
70
+ readonly measured: number;
71
+ readonly already: number;
72
+ readonly failed: number;
73
+ }
74
+ /**
75
+ * The footprint of each plugin of the state, at `MEMORY_PASS_CELLS`, merged into the record its verdict for this run's host
76
+ * came from. One plugin's failure is that plugin's; each record is written whole as its plugin ends, so a pass cut short
77
+ * keeps what it finished, and a pass run again skips those unless `force`.
78
+ */
79
+ export declare function memoryPass(ctx: SyncContext, state: SyncState, options?: {
80
+ readonly force?: boolean;
81
+ readonly run?: ProbeRun;
82
+ }): MemoryPassResult;