tickmarkr 2.5.4 → 2.5.6
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/README.md +3 -1
- package/dist/adapters/registry.js +6 -1
- package/dist/adapters/types.d.ts +3 -0
- package/dist/cli/commands/approve.d.ts +1 -0
- package/dist/cli/commands/approve.js +118 -9
- package/dist/cli/commands/doctor.d.ts +10 -0
- package/dist/cli/commands/doctor.js +44 -29
- package/dist/cli/commands/fleet.js +199 -33
- package/dist/cli/commands/init.js +196 -6
- package/dist/cli/commands/plan.js +20 -4
- package/dist/cli/commands/resume.js +4 -2
- package/dist/cli/commands/run.js +11 -2
- package/dist/cli/commands/verify.js +102 -81
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.js +3 -1
- package/dist/config/config.d.ts +25 -8
- package/dist/config/config.js +41 -29
- package/dist/config/fleet-overlay.d.ts +3 -9
- package/dist/config/fleet-overlay.js +114 -19
- package/dist/config/fleet-why.d.ts +7 -0
- package/dist/config/fleet-why.js +5 -0
- package/dist/drivers/index.d.ts +15 -1
- package/dist/drivers/index.js +39 -10
- package/dist/drivers/orca.d.ts +119 -10
- package/dist/drivers/orca.js +781 -110
- package/dist/gates/baseline.d.ts +17 -3
- package/dist/gates/baseline.js +63 -15
- package/dist/gates/cache.d.ts +101 -0
- package/dist/gates/cache.js +401 -0
- package/dist/gates/llm.d.ts +3 -0
- package/dist/gates/llm.js +11 -0
- package/dist/gates/review.d.ts +28 -3
- package/dist/gates/review.js +106 -14
- package/dist/gates/run-gates.d.ts +9 -1
- package/dist/gates/run-gates.js +407 -102
- package/dist/gates/test-manifest.d.ts +128 -0
- package/dist/gates/test-manifest.js +463 -0
- package/dist/gates/test-reporter.d.ts +4 -0
- package/dist/gates/test-reporter.js +57 -0
- package/dist/graph/graph.d.ts +2 -0
- package/dist/graph/graph.js +45 -1
- package/dist/route/preference.d.ts +22 -1
- package/dist/route/preference.js +123 -25
- package/dist/route/router.js +31 -6
- package/dist/run/consult.js +5 -4
- package/dist/run/daemon.d.ts +15 -0
- package/dist/run/daemon.js +638 -167
- package/dist/run/execution-budget.d.ts +25 -0
- package/dist/run/execution-budget.js +142 -0
- package/dist/run/git.d.ts +50 -1
- package/dist/run/git.js +131 -12
- package/dist/run/journal.d.ts +16 -2
- package/dist/run/journal.js +115 -25
- package/dist/run/lease.d.ts +58 -0
- package/dist/run/lease.js +310 -0
- package/dist/run/merge.d.ts +2 -0
- package/dist/run/merge.js +91 -3
- package/dist/run/operator-state.d.ts +11 -0
- package/dist/run/operator-state.js +17 -3
- package/dist/run/recovery.d.ts +8 -0
- package/dist/run/recovery.js +25 -0
- package/dist/run/repair-selection.d.ts +12 -0
- package/dist/run/repair-selection.js +56 -0
- package/dist/run/stall.d.ts +6 -1
- package/dist/run/stall.js +60 -3
- package/dist/tui/cockpit/board.d.ts +96 -0
- package/dist/tui/cockpit/board.js +346 -0
- package/dist/tui/cockpit/decision-actions.js +2 -0
- package/dist/tui/cockpit/layout.d.ts +5 -1
- package/dist/tui/cockpit/layout.js +8 -3
- package/dist/tui/cockpit/live-runtime.js +71 -21
- package/dist/tui/cockpit/run-view.d.ts +7 -5
- package/dist/tui/cockpit/run-view.js +12 -11
- package/dist/tui/ink/fleet-app.d.ts +49 -27
- package/dist/tui/ink/fleet-app.js +229 -38
- package/package.json +2 -2
- package/skills/tickmarkr-overseer/SKILL.md +173 -113
- package/skills/tickmarkr-overseer/scripts/grade-ci.sh +29 -2
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Box } from "ink";
|
|
3
|
+
import { useContext } from "react";
|
|
3
4
|
import { GLYPHS } from "../../brand.js";
|
|
4
5
|
import { GATE_NAMES } from "../../graph/schema.js";
|
|
5
6
|
import { normalizeGateOutcome } from "../../run/outcome.js";
|
|
6
|
-
import {
|
|
7
|
+
import { BOARD_KEYS, boardFooter, clipBoard, renderBoardLines } from "./board.js";
|
|
8
|
+
import { BodyText, Panel, ShellTheme } from "./components.js";
|
|
7
9
|
import { applyDecisionKey, decisionConfirmLines, decisionKeybar, decisionReceiptLines, initialDecisionSession, } from "./decision-actions.js";
|
|
8
10
|
import { fitCells, wrapCells } from "./width.js";
|
|
9
11
|
/** Bounded history first, then the store's page accessor for an evicted line. */
|
|
@@ -170,15 +172,13 @@ export function runSummaryLine(s) {
|
|
|
170
172
|
}
|
|
171
173
|
const attemptLabel = (t) => (t.attempt !== undefined ? `attempt ${t.attempt}` : t.dispatches === 0 ? "never dispatched" : "attempt unknown");
|
|
172
174
|
const parkOf = (t) => (t.state === "human" ? `human · ${t.parkKind ?? "unknown kind"}` : t.state);
|
|
173
|
-
/**
|
|
174
|
-
export
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
const MATRIX_HEADER = `${"Task".padEnd(4)} ${"state".padEnd(20)} ${GATE_NAMES.map((g) => g.slice(0, 2)).join(" ")} latest attempt`;
|
|
178
|
-
const MATRIX_LEGEND = "P pass · F fail · R running · - not run · D disabled · ? unknown | declaration order, not a timeline · acceptance/review concurrent, optional";
|
|
179
|
-
/** The Run body. Every line is measured through the width module; nothing overflows its column. */
|
|
180
|
-
export function RunView({ snapshot, rows, page, graph, decisions, session, columns, run }) {
|
|
175
|
+
/** The board's footer keys merged with the cockpit's own — every one of them handled by this view or the shell. */
|
|
176
|
+
export const RUN_VIEW_KEYS = [...BOARD_KEYS.slice(0, 2), "←→ verdict gate", "PgUp/PgDn page", "x outcome", "a actions", "o pane", "Tab focus", "? keys", BOARD_KEYS[2]];
|
|
177
|
+
/** The Run body: the approved board (BD-1) over the fold, then the selected task's detail panels. */
|
|
178
|
+
export function RunView({ snapshot, rows, page, graph, decisions, session, columns, run, now = Date.now }) {
|
|
181
179
|
const inner = Math.max(1, Math.floor(columns) - 4);
|
|
180
|
+
const colour = useContext(ShellTheme).mode !== "none";
|
|
181
|
+
const width = Math.max(1, Math.floor(columns));
|
|
182
182
|
const fit = (text) => fitCells(text, inner);
|
|
183
183
|
const decisionLines = (lines) => lines.flatMap((line) => wrapCells(line, inner));
|
|
184
184
|
const lookup = evidenceLookup(rows, page);
|
|
@@ -194,9 +194,10 @@ export function RunView({ snapshot, rows, page, graph, decisions, session, colum
|
|
|
194
194
|
const decision = task === undefined ? undefined : decisions.find((d) => d.taskId === task.id);
|
|
195
195
|
const { menu, confirming, receipt, notice } = session.decisions;
|
|
196
196
|
const blocked = task === undefined ? [] : graph?.tasks.filter((g) => g.deps.includes(task.id)).map((g) => g.id) ?? decision?.blocks ?? [];
|
|
197
|
-
|
|
197
|
+
const board = renderBoardLines({ runId: run.runId, snapshot, graph, now: now(), live: run.live, selection: task?.id, keys: false, colour }, width);
|
|
198
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(BodyText, { emphasis: "dim", children: fitCells(`RUN / ${snapshot.lifecycle} · ${runSummaryLine(snapshot)}`, width) }), board.map((line, i) => _jsx(BodyText, { children: line || " " }, `${i}:${line}`)), tasks.length === 0 && _jsx(BodyText, { children: fitCells("no tasks recorded — no plan", width) }), task !== undefined && (_jsxs(Panel, { title: `SELECTED / ${task.id}${task.title ? ` · ${task.title}` : ""}`, children: [_jsx(BodyText, { children: fit(`state ${parkOf(task)} · ${attemptLabel(task)} · dispatches ${task.dispatches} · path ${task.path ?? "unknown"} · pane ${task.pane ?? "unknown"} · alarm ${task.alarmMs === undefined ? "unknown" : `${task.alarmMs}ms`}${task.mergeEvidence ? ` · merged #L${task.mergeEvidence.line}` : ""}`) }), _jsx(BodyText, { emphasis: "dim", children: fit(`outcome filter ${session.outcomeFilter} (x cycles) · ${shown.length} of ${cells.length} gates shown`) }), shown.map((c) => (_jsx(BodyText, { children: fit(`${c.letter} ${c.gate.padEnd(10)} ${c.labels.join(" · ")}${c.line === undefined ? "" : ` · #L${c.line}`}`) }, c.gate)))] })), verdictCell !== undefined && (_jsxs(Panel, { title: `VERDICT / ${verdictCell.gate}${verdictCell.line === undefined ? "" : ` #L${verdictCell.line}`} · ${verdict.length === 0 ? "no verdict text" : `lines ${from + 1}–${from + window.length} of ${verdict.length}`}`, children: [window.map((line, i) => _jsx(BodyText, { children: fit(`${String(from + i + 1).padStart(4)} ${line}`) }, `${from + i}:${line}`)), _jsx(BodyText, { emphasis: "dim", children: fit("←→ gate · PageUp/PageDown page") })] })), task?.state === "human" && (_jsx(Panel, { title: `PARK / ${task.id}`, children: decision === undefined
|
|
198
199
|
? _jsx(BodyText, { children: fit("park evidence unavailable — refresh before deciding") })
|
|
199
200
|
: (_jsxs(_Fragment, { children: [_jsx(BodyText, { children: fit(`#L${decision.park.line} ${decision.park.kind ?? "unknown kind"}${decision.park.failedGate ? ` · failed gate ${decision.park.failedGate}` : ""} · ${decision.park.reason ?? "no reason recorded"}`) }), _jsx(BodyText, { children: fit(`blocks ${blocked.length === 0 ? "nothing" : blocked.join(", ")} · attempts ${decision.attempts}`) }), _jsx(BodyText, { children: fit(decision.verbs.length === 0 ? `diagnostic: ${decision.diagnostic ?? "no verb"}` : `decisions: ${decision.verbs.join(" · ")} (a Actions)`) }), _jsx(BodyText, { emphasis: "dim", children: fit(run.live ? "matching live daemon enacts a release at its next task boundary" : run.blockingRunId ? `other live run ${run.blockingRunId} holds the lock; resume after it ends` : "no live owner: a release records permission; resume dispatches") })] })) })), menu !== null && (_jsx(Panel, { title: `ACTIONS / ${menu.taskId}`, focused: true, children: menu.verbs.length === 0
|
|
200
201
|
? _jsx(BodyText, { children: fit(`no decision — ${decision?.diagnostic ?? "no verb for this park"}`) })
|
|
201
|
-
: menu.verbs.map((verb, i) => _jsx(BodyText, { emphasis: i === menu.selection ? "strong" : "normal", children: fit(`${i === menu.selection ? `${GLYPHS.pointer} ` : " "}${verb}`) }, verb)) })), confirming !== null && (_jsx(Panel, { title: `CONFIRM ${confirming.command.verb.toUpperCase()}`, focused: true, children: decisionLines(decisionConfirmLines(confirming)).map((line, i) => _jsx(BodyText, { children: line }, `${i}:${line}`)) })), receipt !== null && (_jsx(Panel, { title: receipt.ok ? "RECEIPT · appended" : "RECEIPT · refused", children: decisionLines(decisionReceiptLines(receipt)).map((line, i) => _jsx(BodyText, { children: line }, `${i}:${line}`)) })), notice !== null && _jsx(BodyText, { children: notice }), _jsx(BodyText, { emphasis: "dim", children:
|
|
202
|
+
: menu.verbs.map((verb, i) => _jsx(BodyText, { emphasis: i === menu.selection ? "strong" : "normal", children: fit(`${i === menu.selection ? `${GLYPHS.pointer} ` : " "}${verb}`) }, verb)) })), confirming !== null && (_jsx(Panel, { title: `CONFIRM ${confirming.command.verb.toUpperCase()}`, focused: true, children: decisionLines(decisionConfirmLines(confirming)).map((line, i) => _jsx(BodyText, { children: line }, `${i}:${line}`)) })), receipt !== null && (_jsx(Panel, { title: receipt.ok ? "RECEIPT · appended" : "RECEIPT · refused", children: decisionLines(decisionReceiptLines(receipt)).map((line, i) => _jsx(BodyText, { children: line }, `${i}:${line}`)) })), notice !== null && _jsx(BodyText, { children: notice }), _jsx(BodyText, { emphasis: "dim", children: clipBoard(boardFooter([...RUN_VIEW_KEYS, decisionKeybar(session.decisions, decision)].filter(Boolean), colour), width) })] }));
|
|
202
203
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type AuthHealth, type WorkerAdapter } from "../../adapters/types.js";
|
|
2
|
-
import type { MapEntry, RoutingMode, Tier } from "../../config/config.js";
|
|
2
|
+
import type { MapEntry, RoutingMode, Tier, TickmarkrConfig } from "../../config/config.js";
|
|
3
3
|
import { type Shape } from "../../graph/schema.js";
|
|
4
4
|
export type FleetSteeringKey = "review" | "consult";
|
|
5
5
|
export type FleetEditorState = {
|
|
6
6
|
denyAdapters: string[];
|
|
7
7
|
denyModels: string[];
|
|
8
|
+
/** OBS-1046: the staged routing.allow complement, distinct from the authored deny lists above */
|
|
9
|
+
allowOut?: string[];
|
|
10
|
+
denyWorkersAdapters: string[];
|
|
11
|
+
denyWorkersModels: string[];
|
|
8
12
|
classifications: FleetClassification[];
|
|
9
13
|
selectedMode: RoutingMode;
|
|
10
14
|
map: Record<string, MapEntry>;
|
|
@@ -56,6 +60,17 @@ export type FleetModelEvidence = {
|
|
|
56
60
|
probeMs?: number;
|
|
57
61
|
/** OBS-519: doctor's failed model-auth verdict reason — the row must not render like a healthy one */
|
|
58
62
|
unauthed?: string;
|
|
63
|
+
/** OBS-972/FL-1: a floating alias's resolved concrete model id (e.g. "opus" → "claude-opus-5") */
|
|
64
|
+
identity?: string;
|
|
65
|
+
};
|
|
66
|
+
/** The four staged deny sets every preview and the staged routing policy are computed from. */
|
|
67
|
+
export type FleetStagedDeny = {
|
|
68
|
+
adapters: string[];
|
|
69
|
+
models: string[];
|
|
70
|
+
workersAdapters: string[];
|
|
71
|
+
workersModels: string[];
|
|
72
|
+
/** OBS-1046: the staged routing.allow complement; absent ⇒ the session's initial one */
|
|
73
|
+
allowOut?: string[];
|
|
59
74
|
};
|
|
60
75
|
export type FleetModelGroup = {
|
|
61
76
|
adapter: string;
|
|
@@ -99,35 +114,43 @@ export type FleetCandidateOption = {
|
|
|
99
114
|
};
|
|
100
115
|
};
|
|
101
116
|
export declare function formatDoctorAge(ageMs: number | null): string;
|
|
102
|
-
export
|
|
117
|
+
export type FleetReach = "in" | "out-workers" | "out-all" | "out-allow" | "unknown";
|
|
118
|
+
/** The staged routing policy, or the loader's refusal of the staged overlay. */
|
|
119
|
+
export type FleetStagedRouting = {
|
|
120
|
+
ok: true;
|
|
121
|
+
routing: TickmarkrConfig["routing"];
|
|
122
|
+
} | {
|
|
123
|
+
ok: false;
|
|
124
|
+
error: string;
|
|
125
|
+
};
|
|
126
|
+
export declare function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels, initialAllowOut, initialDenyWorkersAdapters, initialDenyWorkersModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, viewRows, frameColumns, frameRows, }: {
|
|
103
127
|
ageMs: number | null;
|
|
104
128
|
agents: AgentCli[];
|
|
105
129
|
initialDenyAdapters: string[];
|
|
106
130
|
initialDenyModels: string[];
|
|
131
|
+
/** OBS-1046: adapter ids and adapter:model keys routing.allow leaves out of the fleet */
|
|
132
|
+
initialAllowOut?: string[];
|
|
133
|
+
initialDenyWorkersAdapters?: string[];
|
|
134
|
+
initialDenyWorkersModels?: string[];
|
|
107
135
|
modelGroups: FleetModelGroup[];
|
|
108
136
|
initialMode: RoutingMode;
|
|
109
137
|
modeOptions: FleetModeOption[];
|
|
110
138
|
initialMap: Record<string, MapEntry>;
|
|
111
|
-
modePreview: (mode: RoutingMode, map: Record<string, MapEntry>, deny:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}) => string[];
|
|
115
|
-
shapeRows: (mode: RoutingMode, map: Record<string, MapEntry>, deny: {
|
|
116
|
-
adapters: string[];
|
|
117
|
-
models: string[];
|
|
118
|
-
}) => FleetShapeRow[];
|
|
119
|
-
candidatesForShape: (shape: Shape, mode: RoutingMode, map: Record<string, MapEntry>, deny: {
|
|
120
|
-
adapters: string[];
|
|
121
|
-
models: string[];
|
|
122
|
-
}) => {
|
|
139
|
+
modePreview: (mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => string[];
|
|
140
|
+
shapeRows: (mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => FleetShapeRow[];
|
|
141
|
+
candidatesForShape: (shape: Shape, mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => {
|
|
123
142
|
rows: FleetCandidateOption[];
|
|
124
143
|
excludedNote?: string;
|
|
144
|
+
ledger?: string[];
|
|
125
145
|
};
|
|
126
146
|
preferOptionsForShape: (shape: Shape, current: string[]) => string[];
|
|
127
147
|
initialSteering: Record<FleetSteeringKey, string[] | undefined>;
|
|
128
148
|
steeringOptionsFor: (which: FleetSteeringKey, current: string[]) => string[];
|
|
129
149
|
reviewOverlay: (state: FleetEditorState) => FleetOverlayReview;
|
|
130
150
|
reloadGuard: (bytes: string) => string | null;
|
|
151
|
+
/** the routing policy the staged deny sets load as (fleet: the config loader over the candidate
|
|
152
|
+
* bytes); absent ⇒ the four staged sets alone, with no allowlist */
|
|
153
|
+
stagedRouting?: (deny: FleetStagedDeny) => FleetStagedRouting;
|
|
131
154
|
entry?: "presets" | "probe";
|
|
132
155
|
/** resolved config judge as "adapter:model" — shown on the (keep default) picker row */
|
|
133
156
|
initialJudge?: string;
|
|
@@ -140,36 +163,35 @@ export declare function FleetApp({ ageMs, agents, initialDenyAdapters, initialDe
|
|
|
140
163
|
/** terminal height — set only on a real TTY so the footer sticks to the bottom */
|
|
141
164
|
frameRows?: number;
|
|
142
165
|
}): import("react").JSX.Element;
|
|
143
|
-
export declare function runFleetInkEditor({ ageMs, adapters, health, initialDenyAdapters, initialDenyModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, entry, initialJudge, judgeSeats, initialInput, input, output, debug, }: {
|
|
166
|
+
export declare function runFleetInkEditor({ ageMs, adapters, health, initialDenyAdapters, initialDenyModels, initialAllowOut, initialDenyWorkersAdapters, initialDenyWorkersModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, stagedRouting, entry, initialJudge, judgeSeats, initialInput, input, output, debug, }: {
|
|
144
167
|
ageMs: number | null;
|
|
145
168
|
adapters: WorkerAdapter[];
|
|
146
169
|
health: Record<string, AuthHealth>;
|
|
147
170
|
initialDenyAdapters: string[];
|
|
148
171
|
initialDenyModels: string[];
|
|
172
|
+
/** OBS-1046: adapter ids and adapter:model keys routing.allow leaves out of the fleet */
|
|
173
|
+
initialAllowOut?: string[];
|
|
174
|
+
initialDenyWorkersAdapters?: string[];
|
|
175
|
+
initialDenyWorkersModels?: string[];
|
|
149
176
|
modelGroups: FleetModelGroup[];
|
|
150
177
|
initialMode: RoutingMode;
|
|
151
178
|
modeOptions: FleetModeOption[];
|
|
152
179
|
initialMap: Record<string, MapEntry>;
|
|
153
|
-
modePreview: (mode: RoutingMode, map: Record<string, MapEntry>, deny:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}) => string[];
|
|
157
|
-
shapeRows: (mode: RoutingMode, map: Record<string, MapEntry>, deny: {
|
|
158
|
-
adapters: string[];
|
|
159
|
-
models: string[];
|
|
160
|
-
}) => FleetShapeRow[];
|
|
161
|
-
candidatesForShape: (shape: Shape, mode: RoutingMode, map: Record<string, MapEntry>, deny: {
|
|
162
|
-
adapters: string[];
|
|
163
|
-
models: string[];
|
|
164
|
-
}) => {
|
|
180
|
+
modePreview: (mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => string[];
|
|
181
|
+
shapeRows: (mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => FleetShapeRow[];
|
|
182
|
+
candidatesForShape: (shape: Shape, mode: RoutingMode, map: Record<string, MapEntry>, deny: FleetStagedDeny) => {
|
|
165
183
|
rows: FleetCandidateOption[];
|
|
166
184
|
excludedNote?: string;
|
|
185
|
+
ledger?: string[];
|
|
167
186
|
};
|
|
168
187
|
preferOptionsForShape: (shape: Shape, current: string[]) => string[];
|
|
169
188
|
initialSteering: Record<FleetSteeringKey, string[] | undefined>;
|
|
170
189
|
steeringOptionsFor: (which: FleetSteeringKey, current: string[]) => string[];
|
|
171
190
|
reviewOverlay: (state: FleetEditorState) => FleetOverlayReview;
|
|
172
191
|
reloadGuard: (bytes: string) => string | null;
|
|
192
|
+
/** the routing policy the staged deny sets load as (fleet: the config loader over the candidate
|
|
193
|
+
* bytes); absent ⇒ the four staged sets alone, with no allowlist */
|
|
194
|
+
stagedRouting?: (deny: FleetStagedDeny) => FleetStagedRouting;
|
|
173
195
|
/** "presets" = init's entry: Esc in the browser is HOME to the preset overlay, not quit */
|
|
174
196
|
entry?: "presets" | "probe";
|
|
175
197
|
initialJudge?: string;
|