tickmarkr 1.90.6 → 1.90.7

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.
@@ -102,9 +102,15 @@ export function formatDoctorAge(ageMs) {
102
102
  return `${mins}m old`;
103
103
  return `${Math.floor(mins / 60)}h old`;
104
104
  }
105
- export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, }) {
105
+ // judge seats travel the editor as the same "adapter:model" strings the pickers list; the model
106
+ // half may itself contain ":" so only the first separator is structural.
107
+ function splitSeat(seat) {
108
+ const at = seat.indexOf(":");
109
+ return { adapter: seat.slice(0, at), model: seat.slice(at + 1) };
110
+ }
111
+ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, entry = "probe", initialJudge = "", judgeSeats = [], }) {
106
112
  const { exit } = useApp();
107
- const [screen, setScreen] = useState("probe");
113
+ const [screen, setScreen] = useState(entry === "presets" ? "modes" : "probe");
108
114
  const screenRef = useRef(screen);
109
115
  const [cursor, setCursor] = useState(0);
110
116
  const cursorRef = useRef(cursor);
@@ -159,9 +165,19 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
159
165
  const steeringPickerCursorRef = useRef(0);
160
166
  const [steeringPickerCursor, setSteeringPickerCursor] = useState(0);
161
167
  const [, setSteeringPickerRevision] = useState(0);
168
+ const judgeCursorRef = useRef(0);
169
+ const [judgeCursor, setJudgeCursor] = useState(0);
170
+ const judgeSeatRef = useRef(null);
171
+ const [judgeSeat, setJudgeSeat] = useState(null);
162
172
  const reviewRef = useRef(null);
163
173
  const [review, setReview] = useState(null);
164
174
  const doneRef = useRef(false);
175
+ // entry === "presets": the first modes visit is the preset pick (mode → review, custom → the
176
+ // full walk). Once custom is chosen this flips off and modes behaves exactly as in probe entry.
177
+ const presetPickRef = useRef(entry === "presets");
178
+ // type-to-search on the long lists — reset on every screen change (per-screen-visit filter)
179
+ const filterRef = useRef("");
180
+ const [filter, setFilter] = useState("");
165
181
  const enabledModelGroups = () => modelGroups.filter((group) => !denyRef.current?.has(group.adapter));
166
182
  const stagedMap = () => mapRef.current;
167
183
  const currentModelRows = () => {
@@ -180,6 +196,31 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
180
196
  }
181
197
  return rows;
182
198
  };
199
+ // type-to-search over the long lists: plain case-insensitive substring on the row's visible
200
+ // label. Each filterable screen derives its rows through these so input and render agree.
201
+ const matches = (label, f = filterRef.current) => f === "" || label.toLowerCase().includes(f.toLowerCase());
202
+ const filteredModelRows = (f = filterRef.current) => currentModelRows().filter((row) => matches(row.model, f));
203
+ const filteredCandidates = (f = filterRef.current) => candidatesRef.current.filter((candidate) => matches(candidate.label, f));
204
+ const filteredSteeringRows = (f = filterRef.current) => steeringRowsRef.current.filter((option) => matches(option, f));
205
+ const judgeKeepRow = initialJudge ? `(keep default) ${initialJudge}` : "(keep default)";
206
+ const filteredJudgeRows = (f = filterRef.current) => [judgeKeepRow, ...judgeSeats].filter((row) => matches(row, f));
207
+ // Shared filter-edit tail for the filterable screens: hotkeys run first in each screen block,
208
+ // whatever printable input is left appends here (space stays a toggle key, never a filter char).
209
+ const filterInput = (countFor, cursorRef, setCursorState, input, key) => {
210
+ // printable chars only: "\r" reaches here when an emptied list makes key.return a no-op
211
+ const printable = input > " " && !key.ctrl && !key.meta;
212
+ const next = key.backspace || key.delete
213
+ ? filterRef.current.slice(0, -1)
214
+ : (printable ? filterRef.current + input : null);
215
+ if (next === null)
216
+ return false;
217
+ filterRef.current = next;
218
+ setFilter(next);
219
+ const clamped = Math.min(cursorRef.current, Math.max(countFor(next) - 1, 0));
220
+ cursorRef.current = clamped;
221
+ setCursorState(clamped);
222
+ return true;
223
+ };
183
224
  const editorState = () => ({
184
225
  denyAdapters: [...(denyRef.current ?? [])].sort(),
185
226
  denyModels: [...(denyModelsRef.current ?? [])].sort(),
@@ -194,6 +235,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
194
235
  : classification),
195
236
  selectedMode: selectedModeRef.current,
196
237
  map: stagedMap(),
238
+ ...(judgeSeatRef.current ? { judgeSeat: splitSeat(judgeSeatRef.current) } : {}),
197
239
  steering: structuredClone(steeringRef.current),
198
240
  });
199
241
  const finish = (result) => {
@@ -206,9 +248,24 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
206
248
  showScreen("steering");
207
249
  };
208
250
  const showScreen = (next) => {
251
+ filterRef.current = "";
252
+ setFilter("");
209
253
  screenRef.current = next;
210
254
  setScreen(next);
211
255
  };
256
+ // The one review funnel: an empty staged overlay finishes as no-changes, a real diff shows the
257
+ // confirm screen. Reached from the steering enter and, in preset entry, from a mode pick.
258
+ const goReview = () => {
259
+ const nextReview = reviewOverlay(editorState());
260
+ if (nextReview.kind === "empty") {
261
+ finish({ kind: "no-changes" });
262
+ return;
263
+ }
264
+ reviewRef.current = nextReview;
265
+ setReview(reviewRef.current);
266
+ setNotice("");
267
+ showScreen("review");
268
+ };
212
269
  const beginClassification = (group, model) => {
213
270
  tierCursorRef.current = 0;
214
271
  setTierCursor(0);
@@ -248,7 +305,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
248
305
  showScreen("shapes");
249
306
  return;
250
307
  }
251
- if (key.escape && screenRef.current === "steering-prefer") {
308
+ if (key.escape && (screenRef.current === "steering-prefer" || screenRef.current === "judge-pick")) {
252
309
  showScreen("steering");
253
310
  return;
254
311
  }
@@ -304,7 +361,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
304
361
  return;
305
362
  }
306
363
  if (screenRef.current === "models") {
307
- const rows = currentModelRows();
364
+ const rows = filteredModelRows();
308
365
  if (key.downArrow || input === "j") {
309
366
  const next = Math.min(modelCursorRef.current + 1, Math.max(rows.length - 1, 0));
310
367
  modelCursorRef.current = next;
@@ -354,10 +411,16 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
354
411
  setModelGroup(next);
355
412
  modelCursorRef.current = 0;
356
413
  setModelCursor(0);
414
+ filterRef.current = "";
415
+ setFilter("");
357
416
  }
358
417
  else {
359
418
  showScreen("modes");
360
419
  }
420
+ return;
421
+ }
422
+ if (filterInput((f) => filteredModelRows(f).length, modelCursorRef, setModelCursor, input, key)) {
423
+ setNotice("");
361
424
  }
362
425
  return;
363
426
  }
@@ -464,9 +527,11 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
464
527
  }
465
528
  }
466
529
  if (screenRef.current === "modes") {
530
+ // preset entry adds one final `custom` row after the modes — the full-walk escape hatch
531
+ const rowCount = modeOptions.length + (presetPickRef.current ? 1 : 0);
467
532
  const currentModeCursor = modeCursorRef.current ?? 0;
468
533
  if (key.downArrow || input === "j") {
469
- const next = Math.min(currentModeCursor + 1, Math.max(modeOptions.length - 1, 0));
534
+ const next = Math.min(currentModeCursor + 1, Math.max(rowCount - 1, 0));
470
535
  modeCursorRef.current = next;
471
536
  setModeCursor(next);
472
537
  return;
@@ -477,8 +542,20 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
477
542
  setModeCursor(next);
478
543
  return;
479
544
  }
480
- if (key.return && modeOptions[currentModeCursor]) {
545
+ if (key.return) {
546
+ if (presetPickRef.current && currentModeCursor === modeOptions.length) {
547
+ presetPickRef.current = false;
548
+ showScreen("agents");
549
+ return;
550
+ }
551
+ if (!modeOptions[currentModeCursor])
552
+ return;
481
553
  selectedModeRef.current = modeOptions[currentModeCursor].id;
554
+ if (presetPickRef.current) {
555
+ // entry context: a preset pick goes straight to the diff confirm
556
+ goReview();
557
+ return;
558
+ }
482
559
  showScreen("shapes");
483
560
  }
484
561
  return;
@@ -527,8 +604,9 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
527
604
  return;
528
605
  }
529
606
  if (screenRef.current === "candidates") {
607
+ const rows = filteredCandidates();
530
608
  if (key.downArrow || input === "j") {
531
- const next = Math.min(candidateCursorRef.current + 1, Math.max(candidatesRef.current.length - 1, 0));
609
+ const next = Math.min(candidateCursorRef.current + 1, Math.max(rows.length - 1, 0));
532
610
  candidateCursorRef.current = next;
533
611
  setCandidateCursor(next);
534
612
  return;
@@ -539,16 +617,18 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
539
617
  setCandidateCursor(next);
540
618
  return;
541
619
  }
542
- if (key.return && candidatesRef.current[candidateCursorRef.current]) {
620
+ if (key.return && rows[candidateCursorRef.current]) {
543
621
  const shape = shapeRows(selectedModeRef.current, stagedMap())[shapeCursorRef.current]?.id;
544
622
  if (shape) {
545
- const picked = candidatesRef.current[candidateCursorRef.current];
623
+ const picked = rows[candidateCursorRef.current];
546
624
  const nextMap = { ...stagedMap(), [shape]: { pin: picked.pin } };
547
625
  mapRef.current = nextMap;
548
626
  setMap(nextMap);
549
627
  }
550
628
  showScreen("shapes");
629
+ return;
551
630
  }
631
+ filterInput((f) => filteredCandidates(f).length, candidateCursorRef, setCandidateCursor, input, key);
552
632
  return;
553
633
  }
554
634
  if (screenRef.current === "shape-prefer") {
@@ -591,8 +671,9 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
591
671
  return;
592
672
  }
593
673
  if (screenRef.current === "steering") {
674
+ // review.prefer + consult.prefer rows plus the single judge seat as the final row
594
675
  if (key.downArrow || input === "j") {
595
- const next = Math.min(steeringCursorRef.current + 1, STEERING_KEYS.length - 1);
676
+ const next = Math.min(steeringCursorRef.current + 1, STEERING_KEYS.length);
596
677
  steeringCursorRef.current = next;
597
678
  setSteeringCursor(next);
598
679
  return;
@@ -604,6 +685,13 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
604
685
  return;
605
686
  }
606
687
  if (input === "f") {
688
+ if (steeringCursorRef.current === STEERING_KEYS.length) {
689
+ judgeCursorRef.current = 0;
690
+ setJudgeCursor(0);
691
+ setNotice("");
692
+ showScreen("judge-pick");
693
+ return;
694
+ }
607
695
  const which = STEERING_KEYS[steeringCursorRef.current];
608
696
  const current = steeringRef.current?.[which] ?? [];
609
697
  steeringPickerRef.current = which;
@@ -615,22 +703,40 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
615
703
  showScreen("steering-prefer");
616
704
  return;
617
705
  }
618
- if (key.return) {
619
- const nextReview = reviewOverlay(editorState());
620
- if (nextReview.kind === "empty") {
621
- finish({ kind: "no-changes" });
622
- return;
623
- }
624
- reviewRef.current = nextReview;
625
- setReview(nextReview);
626
- setNotice("");
627
- showScreen("review");
706
+ if (key.return)
707
+ goReview();
708
+ return;
709
+ }
710
+ if (screenRef.current === "judge-pick") {
711
+ const rows = filteredJudgeRows();
712
+ if (key.downArrow || input === "j") {
713
+ const next = Math.min(judgeCursorRef.current + 1, Math.max(rows.length - 1, 0));
714
+ judgeCursorRef.current = next;
715
+ setJudgeCursor(next);
716
+ return;
628
717
  }
718
+ if (key.upArrow || input === "k") {
719
+ const next = Math.max(judgeCursorRef.current - 1, 0);
720
+ judgeCursorRef.current = next;
721
+ setJudgeCursor(next);
722
+ return;
723
+ }
724
+ if (key.return && rows[judgeCursorRef.current]) {
725
+ // single-select: one seat or back to the config default — never a chain
726
+ const picked = rows[judgeCursorRef.current];
727
+ const seat = picked === judgeKeepRow ? null : picked;
728
+ judgeSeatRef.current = seat;
729
+ setJudgeSeat(seat);
730
+ showScreen("steering");
731
+ return;
732
+ }
733
+ filterInput((f) => filteredJudgeRows(f).length, judgeCursorRef, setJudgeCursor, input, key);
629
734
  return;
630
735
  }
631
736
  if (screenRef.current === "steering-prefer") {
737
+ const rows = filteredSteeringRows();
632
738
  if (key.downArrow || input === "j") {
633
- const next = Math.min(steeringPickerCursorRef.current + 1, Math.max(steeringRowsRef.current.length - 1, 0));
739
+ const next = Math.min(steeringPickerCursorRef.current + 1, Math.max(rows.length - 1, 0));
634
740
  steeringPickerCursorRef.current = next;
635
741
  setSteeringPickerCursor(next);
636
742
  return;
@@ -641,8 +747,8 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
641
747
  setSteeringPickerCursor(next);
642
748
  return;
643
749
  }
644
- if (input === " " && steeringRowsRef.current[steeringPickerCursorRef.current]) {
645
- const option = steeringRowsRef.current[steeringPickerCursorRef.current];
750
+ if (input === " " && rows[steeringPickerCursorRef.current]) {
751
+ const option = rows[steeringPickerCursorRef.current];
646
752
  const at = steeringChainRef.current.indexOf(option);
647
753
  if (at === -1)
648
754
  steeringChainRef.current.push(option);
@@ -661,7 +767,9 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
661
767
  setSteering(next);
662
768
  setNotice("");
663
769
  showScreen("steering");
770
+ return;
664
771
  }
772
+ filterInput((f) => filteredSteeringRows(f).length, steeringPickerCursorRef, setSteeringPickerCursor, input, key);
665
773
  return;
666
774
  }
667
775
  if (screenRef.current === "review") {
@@ -675,7 +783,7 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
675
783
  setNotice(`fleet: config loader rejects the proposed overlay — ${loadError}`);
676
784
  reviewRef.current = null;
677
785
  setReview(null);
678
- showScreen("steering");
786
+ showScreen(presetPickRef.current ? "modes" : "steering");
679
787
  return;
680
788
  }
681
789
  finish({ kind: "write", review: reviewRef.current });
@@ -699,16 +807,15 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
699
807
  return (_jsx(FleetListScreen, { title: "step 2/6 \u00B7 agent CLIs", legend: "\u2191\u2193/jk move \u00B7 space toggle \u00B7 enter next \u00B7 esc/q quit", rows: rows, cursor: cursor }));
700
808
  }
701
809
  const group = enabledModelGroups()[modelGroup];
702
- const modelRows = currentModelRows();
703
810
  if (screen === "models") {
704
- const rows = modelRows.map((row) => {
811
+ const rows = filteredModelRows().map((row) => {
705
812
  const denied = group ? denyModels.has(`${group.adapter}:${row.model}`) : false;
706
813
  return {
707
814
  id: row.model,
708
815
  content: row.tier ? (_jsxs(_Fragment, { children: [_jsx(ToggleMark, { active: !denied }), _jsx(Text, { children: ` ${row.model} ${row.tier} ${denied ? "denied" : "allowed"}` })] })) : _jsx(Text, { children: `( ) ${row.model} ??? unclassified${row.detectedAt ? ` (${row.detectedAt})` : ""}` }),
709
816
  };
710
817
  });
711
- return (_jsx(FleetListScreen, { title: `step 3/6 · models · ${group?.adapter ?? ""}`, legend: "\u2191\u2193/jk move \u00B7 space toggle \u00B7 t tier \u00B7 n add model \u00B7 enter next \u00B7 esc/q quit", rows: rows, cursor: modelCursor, details: notice ? [notice] : [] }));
818
+ return (_jsx(FleetListScreen, { title: `step 3/6 · models · ${group?.adapter ?? ""}`, legend: "\u2191\u2193 to move \u00B7 Space to toggle \u00B7 t to classify tier \u00B7 n to add model \u00B7 Enter for next \u00B7 Type to search \u00B7 Esc to quit", rows: rows, cursor: modelCursor, details: notice ? [notice] : [], filter: filter }));
712
819
  }
713
820
  if (screen === "add-model")
714
821
  return (_jsx(FleetListScreen, { title: `add model · ${group?.adapter ?? ""}`, legend: "type model id \u00B7 enter classify \u00B7 esc cancel", rows: [{ id: "model", content: _jsx(Text, { children: modelId || "model id (required):" }) }], cursor: 0, details: notice ? [notice] : [] }));
@@ -720,10 +827,18 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
720
827
  if (screen === "provenance")
721
828
  return (_jsx(FleetListScreen, { title: `benchmark provenance · ${pendingClassificationRef.current?.adapter}:${pendingClassificationRef.current?.model}`, legend: "type note \u00B7 enter apply \u00B7 esc cancel", rows: [{ id: "note", content: _jsx(Text, { children: note || "benchmark provenance note (required):" }) }], cursor: 0, details: notice ? [notice] : [] }));
722
829
  if (screen === "modes") {
723
- return (_jsx(FleetListScreen, { title: "step 4/6 \u00B7 routing mode", legend: "\u2191\u2193/jk move \u00B7 enter select \u00B7 esc/q quit", rows: modeOptions.map((option) => ({
724
- id: option.id,
725
- content: (_jsxs(_Fragment, { children: [option.id === initialMode ? _jsx(ToggleMark, { active: true }) : _jsx(Text, { children: " " }), _jsx(Text, { children: ` ${option.id.padEnd(11)} ${option.gloss}` })] })),
726
- })), cursor: modeCursor, details: modePreview(modeOptions[modeCursor].id, map) }));
830
+ const presetPick = presetPickRef.current;
831
+ const rows = modeOptions.map((option) => ({
832
+ id: option.id,
833
+ content: (_jsxs(_Fragment, { children: [option.id === initialMode ? _jsx(ToggleMark, { active: true }) : _jsx(Text, { children: " " }), _jsx(Text, { children: ` ${option.id.padEnd(11)} ${option.gloss}` })] })),
834
+ }));
835
+ if (presetPick) {
836
+ rows.push({
837
+ id: "custom",
838
+ content: (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { children: ` ${"custom".padEnd(11)} walk the full editor (agents → models → shapes → seats)` })] })),
839
+ });
840
+ }
841
+ return (_jsx(FleetListScreen, { title: presetPick ? "fleet · routing presets" : "step 4/6 · routing mode", legend: presetPick ? "↑↓ to move · Enter to apply preset · Esc to close" : "↑↓/jk move · enter select · esc/q quit", rows: rows, cursor: modeCursor, details: modeOptions[modeCursor] ? modePreview(modeOptions[modeCursor].id, map) : [] }));
727
842
  }
728
843
  const renderedShapes = shapeRows(selectedModeRef.current, map);
729
844
  if (screen === "shapes") {
@@ -731,10 +846,10 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
731
846
  }
732
847
  const shape = renderedShapes[shapeCursor]?.id;
733
848
  if (screen === "candidates") {
734
- return (_jsx(FleetListScreen, { title: `pick · ${shape}`, legend: "\u2191\u2193/jk move \u00B7 enter pin \u00B7 esc cancel \u00B7 q quit", rows: candidatesRef.current.map((candidate) => ({
849
+ return (_jsx(FleetListScreen, { title: `pick · ${shape}`, legend: "\u2191\u2193 to move \u00B7 Enter to pin \u00B7 Type to search \u00B7 Esc to cancel \u00B7 q to quit", rows: filteredCandidates().map((candidate) => ({
735
850
  id: candidate.id,
736
851
  content: _jsx(Text, { children: candidate.label }),
737
- })), cursor: candidateCursor }));
852
+ })), cursor: candidateCursor, filter: filter }));
738
853
  }
739
854
  if (screen === "shape-prefer")
740
855
  return (_jsx(FleetListScreen, { title: `pick · ${shape}.prefer`, legend: "\u2191\u2193/jk move \u00B7 space add/drop \u00B7 enter apply (empty clears) \u00B7 esc cancel \u00B7 q quit", rows: preferRowsRef.current.map((option) => {
@@ -742,21 +857,34 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
742
857
  return { id: option, content: _jsx(Text, { children: `${at === -1 ? "·" : String(at + 1)} ${option}` }) };
743
858
  }), cursor: preferCursor }));
744
859
  if (screen === "steering") {
745
- return (_jsx(FleetListScreen, { title: "step 6/6 \u00B7 steering", legend: "\u2191\u2193/jk move \u00B7 f prefer \u00B7 enter review \u00B7 esc/q quit", rows: STEERING_KEYS.map((key) => ({
746
- id: key,
747
- content: _jsx(Text, { children: `${key}.prefer → ${steering[key]?.join(", ") ?? "(none)"}` }),
748
- })), cursor: steeringCursor, details: notice ? [notice] : [] }));
860
+ return (_jsx(FleetListScreen, { title: "step 6/6 \u00B7 steering", legend: "\u2191\u2193 to move \u00B7 f to edit \u00B7 Enter to review \u00B7 Esc/q to quit", rows: [
861
+ ...STEERING_KEYS.map((key) => ({
862
+ id: key,
863
+ content: _jsx(Text, { children: `${key}.prefer → ${steering[key]?.join(", ") ?? "(none)"}` }),
864
+ })),
865
+ {
866
+ id: "judge",
867
+ content: _jsx(Text, { children: `judge → ${judgeSeat ?? (initialJudge ? `${initialJudge} (default)` : "(default)")}` }),
868
+ },
869
+ ], cursor: steeringCursor, details: notice ? [notice] : [] }));
870
+ }
871
+ if (screen === "judge-pick") {
872
+ const selected = judgeSeat ?? judgeKeepRow;
873
+ return (_jsx(FleetListScreen, { title: "pick \u00B7 judge", legend: "\u2191\u2193 to move \u00B7 Enter to select \u00B7 Type to search \u00B7 Esc to cancel \u00B7 q to quit", rows: filteredJudgeRows().map((label) => ({
874
+ id: label,
875
+ content: (_jsxs(_Fragment, { children: [label === selected ? _jsx(ToggleMark, { active: true }) : _jsx(Text, { children: " " }), _jsx(Text, { children: ` ${label}` })] })),
876
+ })), cursor: judgeCursor, filter: filter }));
749
877
  }
750
878
  if (screen === "steering-prefer") {
751
879
  const which = steeringPickerRef.current;
752
- return (_jsx(FleetListScreen, { title: `pick · ${which}.prefer`, legend: "\u2191\u2193/jk move \u00B7 space add/drop \u00B7 enter apply (empty clears) \u00B7 esc cancel \u00B7 q quit", rows: steeringRowsRef.current.map((option) => {
880
+ return (_jsx(FleetListScreen, { title: `pick · ${which}.prefer`, legend: "\u2191\u2193 to move \u00B7 Space to add/drop \u00B7 Enter to apply (empty clears) \u00B7 Type to search \u00B7 Esc to cancel \u00B7 q to quit", rows: filteredSteeringRows().map((option) => {
753
881
  const at = steeringChainRef.current.indexOf(option);
754
882
  return { id: option, content: _jsx(Text, { children: `${at === -1 ? "·" : String(at + 1)} ${option}` }) };
755
- }), cursor: steeringPickerCursor }));
883
+ }), cursor: steeringPickerCursor, filter: filter }));
756
884
  }
757
885
  return (_jsx(FleetReviewScreen, { title: "review \u00B7 overlay diff", legend: "y write \u00B7 n discard \u00B7 esc/q quit", diff: review?.diff ?? "" }));
758
886
  }
759
- export async function runFleetInkEditor({ ageMs, adapters, health, initialDenyAdapters, initialDenyModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, initialInput = [], input, output, debug = false, }) {
887
+ export async function runFleetInkEditor({ ageMs, adapters, health, initialDenyAdapters, initialDenyModels, modelGroups, initialMode, modeOptions, initialMap, modePreview, shapeRows, candidatesForShape, preferOptionsForShape, initialSteering, steeringOptionsFor, reviewOverlay, reloadGuard, entry = "probe", initialJudge = "", judgeSeats = [], initialInput = [], input, output, debug = false, }) {
760
888
  const agents = adapters.flatMap((adapter) => {
761
889
  const state = health[adapter.id];
762
890
  if (!state?.installed)
@@ -774,7 +902,7 @@ export async function runFleetInkEditor({ ageMs, adapters, health, initialDenyAd
774
902
  }));
775
903
  const bridgedInput = inkInput(input, initialInput);
776
904
  const legacyOutput = typeof output.on !== "function" || typeof output.off !== "function";
777
- const app = render(_jsx(FleetApp, { ageMs: ageMs, agents: agents, initialDenyAdapters: initialDenyAdapters, initialDenyModels: initialDenyModels, modelGroups: declaredModelGroups, initialMode: initialMode, modeOptions: modeOptions, initialMap: initialMap, modePreview: modePreview, shapeRows: shapeRows, candidatesForShape: candidatesForShape, preferOptionsForShape: preferOptionsForShape, initialSteering: initialSteering, steeringOptionsFor: steeringOptionsFor, reviewOverlay: reviewOverlay, reloadGuard: reloadGuard }), {
905
+ const app = render(_jsx(FleetApp, { ageMs: ageMs, agents: agents, initialDenyAdapters: initialDenyAdapters, initialDenyModels: initialDenyModels, modelGroups: declaredModelGroups, initialMode: initialMode, modeOptions: modeOptions, initialMap: initialMap, modePreview: modePreview, shapeRows: shapeRows, candidatesForShape: candidatesForShape, preferOptionsForShape: preferOptionsForShape, initialSteering: initialSteering, steeringOptionsFor: steeringOptionsFor, reviewOverlay: reviewOverlay, reloadGuard: reloadGuard, entry: entry, initialJudge: initialJudge, judgeSeats: judgeSeats }), {
778
906
  // FleetIO's injected stream predates Ink and did not require ref/unref.
779
907
  // Real terminal streams pass through unchanged; the compatibility facade
780
908
  // adds only those lifecycle methods and leaves input decoding to Ink.
@@ -0,0 +1,34 @@
1
+ import type { InitConfigOverlay } from "../../config/config.js";
2
+ type Driver = NonNullable<InitConfigOverlay["driver"]>;
3
+ type VisibilityLlm = NonNullable<NonNullable<InitConfigOverlay["visibility"]>["llm"]>;
4
+ export type InitWizardFields = {
5
+ driver: Driver;
6
+ concurrency: number;
7
+ visibilityLlm: VisibilityLlm;
8
+ offerSkills: boolean;
9
+ skillsDefault: boolean;
10
+ };
11
+ export type InitWizardResult = {
12
+ kind: "continue";
13
+ overlay: {
14
+ driver: Driver;
15
+ concurrency: number;
16
+ visibility: {
17
+ llm: VisibilityLlm;
18
+ };
19
+ };
20
+ installSkills: boolean;
21
+ installDocs: boolean;
22
+ } | {
23
+ kind: "quit";
24
+ };
25
+ export declare function InitWizardApp({ fields }: {
26
+ fields: InitWizardFields;
27
+ }): import("react").JSX.Element;
28
+ export declare function runInitWizardApp(opts: {
29
+ fields: InitWizardFields;
30
+ input: NodeJS.ReadStream;
31
+ output: NodeJS.WriteStream;
32
+ initialInput?: string[];
33
+ }): Promise<InitWizardResult>;
34
+ export {};