@heretek-ai/epistemic-swarm 1.1.3 → 1.6.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/dist/tui.js CHANGED
@@ -1,26 +1,207 @@
1
1
  // @bun
2
2
  // src/tui.tsx
3
- import { userInfo } from "os";
3
+ import { userInfo as userInfo2 } from "os";
4
4
  import { Plugin } from "@opencode/plugin/tui";
5
5
 
6
- // src/panels.tsx
7
- import { mergeProps as _$mergeProps } from "@opentui/solid";
8
- import { memo as _$memo } from "@opentui/solid";
6
+ // src/approve-tui.ts
7
+ import { userInfo } from "os";
8
+ import {
9
+ approveStage,
10
+ checkApprovalAttempts,
11
+ stateDir as defaultStateDir,
12
+ exists,
13
+ factoryLayout,
14
+ HumanKeyError,
15
+ hasHumanKey,
16
+ noteApprovalSuccess,
17
+ noteWrongPassphrase,
18
+ unlockHumanKey,
19
+ zeroCodepoints
20
+ } from "@heretek-ai/es-core";
21
+ var TERMINAL_FALLBACK = (stage) => `Run \`es approve ${stage}\` at a terminal with your passphrase (approvals need the sealed human key).`;
22
+ var APPROVAL_PREVIEW_TTL_MS = 120000;
23
+ async function approveInTui(input) {
24
+ const dir = input.stateDir ?? defaultStateDir();
25
+ if (!await exists(factoryLayout(input.root).dir) || !await hasHumanKey(dir))
26
+ return { ok: false, fallback: true, reason: TERMINAL_FALLBACK(input.stage) };
27
+ const gate = await checkApprovalAttempts(dir);
28
+ if (!gate.allowed)
29
+ return { ok: false, locked: true, retryAfterSec: gate.retryAfterSec ?? 0 };
30
+ const title = `Approve ${input.stage} as ${input.approvedBy ?? userInfo().username}`;
31
+ for (;; ) {
32
+ const codepoints = await input.readPassphrase(title);
33
+ if (codepoints === undefined)
34
+ return { ok: false, cancelled: true };
35
+ const passphrase = codepoints.join("");
36
+ zeroCodepoints(codepoints);
37
+ try {
38
+ const signer = await unlockHumanKey(passphrase, dir);
39
+ try {
40
+ const now = input.now ?? Date.now;
41
+ if (input.previewIssuedAt !== undefined && now() - input.previewIssuedAt > APPROVAL_PREVIEW_TTL_MS)
42
+ throw new Error("The approval preview expired (> 120 s old); preview again.");
43
+ if (input.previewToken !== undefined && input.redeemPreview !== undefined)
44
+ await input.redeemPreview(input.previewToken);
45
+ await noteApprovalSuccess(dir);
46
+ const { record } = await approveStage(input.root, {
47
+ stage: input.stage,
48
+ channel: "tui",
49
+ signer,
50
+ ...input.approvedBy ? { approvedBy: input.approvedBy } : {},
51
+ stateDir: dir,
52
+ expectedSubjectHash: input.expectedSubjectHash
53
+ });
54
+ return { ok: true, record };
55
+ } finally {
56
+ signer.destroy();
57
+ }
58
+ } catch (error) {
59
+ if (error instanceof HumanKeyError && error.message === "wrong passphrase") {
60
+ const check = await noteWrongPassphrase({ dir, root: input.root, stage: input.stage, channel: "tui" });
61
+ if (!check.allowed)
62
+ return { ok: false, locked: true, retryAfterSec: check.retryAfterSec ?? 0 };
63
+ continue;
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ }
69
+
70
+ // src/masked-input.tsx
9
71
  import { createComponent as _$createComponent } from "@opentui/solid";
10
72
  import { createTextNode as _$createTextNode } from "@opentui/solid";
11
73
  import { insertNode as _$insertNode } from "@opentui/solid";
74
+ import { memo as _$memo } from "@opentui/solid";
12
75
  import { insert as _$insert } from "@opentui/solid";
13
76
  import { setProp as _$setProp } from "@opentui/solid";
14
77
  import { createElement as _$createElement } from "@opentui/solid";
15
- import { createResource, createSignal, For, onCleanup, Show } from "solid-js";
78
+ import { zeroCodepoints as zeroCodepoints2 } from "@heretek-ai/es-core";
79
+ import { useKeyboard, usePaste } from "@opentui/solid";
80
+ import { createSignal, onCleanup } from "solid-js";
81
+ function MaskedInput(props) {
82
+ const codepoints = [];
83
+ const [count, setCount] = createSignal(0);
84
+ const [cancelled, setCancelled] = createSignal(false);
85
+ let done = false;
86
+ const finish = (submit) => {
87
+ if (done)
88
+ return;
89
+ done = true;
90
+ try {
91
+ if (submit)
92
+ props.onSubmit(codepoints);
93
+ else
94
+ props.onCancel();
95
+ } finally {
96
+ zeroCodepoints2(codepoints);
97
+ setCount(0);
98
+ }
99
+ };
100
+ onCleanup(() => {
101
+ zeroCodepoints2(codepoints);
102
+ setCount(0);
103
+ });
104
+ useKeyboard((key) => {
105
+ if (done)
106
+ return;
107
+ if (key.name === "return" || key.name === "enter") {
108
+ key.preventDefault();
109
+ key.stopPropagation();
110
+ finish(true);
111
+ return;
112
+ }
113
+ if (key.name === "escape" || key.name === "c" && key.ctrl) {
114
+ key.preventDefault();
115
+ key.stopPropagation();
116
+ setCancelled(true);
117
+ finish(false);
118
+ return;
119
+ }
120
+ if (key.name === "backspace") {
121
+ key.preventDefault();
122
+ key.stopPropagation();
123
+ if (codepoints.length > 0) {
124
+ codepoints.pop();
125
+ setCount(codepoints.length);
126
+ }
127
+ return;
128
+ }
129
+ if (!key.ctrl && !key.meta && key.sequence && [...key.sequence].length === 1) {
130
+ key.preventDefault();
131
+ key.stopPropagation();
132
+ for (const point of key.sequence)
133
+ codepoints.push(point);
134
+ setCount(codepoints.length);
135
+ return;
136
+ }
137
+ key.preventDefault();
138
+ key.stopPropagation();
139
+ });
140
+ usePaste((event) => {
141
+ if (done)
142
+ return;
143
+ event.preventDefault();
144
+ event.stopPropagation();
145
+ const text = new TextDecoder().decode(event.bytes).replace(/[\r\n]+/g, "");
146
+ if (text) {
147
+ for (const point of text)
148
+ codepoints.push(point);
149
+ setCount(codepoints.length);
150
+ }
151
+ });
152
+ return (() => {
153
+ var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("text"), _el$4 = _$createElement("text");
154
+ _$insertNode(_el$, _el$2);
155
+ _$insertNode(_el$, _el$3);
156
+ _$insertNode(_el$, _el$4);
157
+ _$setProp(_el$, "flexDirection", "column");
158
+ _$setProp(_el$, "padding", 1);
159
+ _$setProp(_el$, "gap", 1);
160
+ _$insert(_el$2, () => props.title);
161
+ _$insert(_el$3, (() => {
162
+ var _c$ = _$memo(() => !!cancelled());
163
+ return () => _c$() ? "Cancelled." : `Passphrase: ${"\u2022".repeat(count())}`;
164
+ })());
165
+ _$insertNode(_el$4, _$createTextNode(`Enter submits \xB7 Esc cancels \xB7 paste accepted as one unit`));
166
+ return _el$;
167
+ })();
168
+ }
169
+ function readMaskedPassphrase(dialog, title) {
170
+ return new Promise((resolve) => {
171
+ let settled = false;
172
+ const done = (codepoints) => {
173
+ if (settled)
174
+ return;
175
+ settled = true;
176
+ dialog.clear();
177
+ resolve(codepoints === undefined ? undefined : [...codepoints]);
178
+ };
179
+ dialog.show(() => _$createComponent(MaskedInput, {
180
+ title,
181
+ onSubmit: (codepoints) => done(codepoints),
182
+ onCancel: () => done(undefined)
183
+ }), () => done(undefined));
184
+ });
185
+ }
186
+
187
+ // src/panels.tsx
188
+ import { mergeProps as _$mergeProps } from "@opentui/solid";
189
+ import { memo as _$memo2 } from "@opentui/solid";
190
+ import { createComponent as _$createComponent2 } from "@opentui/solid";
191
+ import { createTextNode as _$createTextNode2 } from "@opentui/solid";
192
+ import { insertNode as _$insertNode2 } from "@opentui/solid";
193
+ import { insert as _$insert2 } from "@opentui/solid";
194
+ import { setProp as _$setProp2 } from "@opentui/solid";
195
+ import { createElement as _$createElement2 } from "@opentui/solid";
196
+ import { createResource, createSignal as createSignal2, For, onCleanup as onCleanup2, Show } from "solid-js";
16
197
  var PANEL_REFRESH_MS = 2000;
17
198
  var FOOTER_REFRESH_MS = 5000;
18
199
  function usePanelState(props, method, everyMs = PANEL_REFRESH_MS) {
19
- const [version, setVersion] = createSignal(0);
200
+ const [version, setVersion] = createSignal2(0);
20
201
  const bump = () => setVersion((value) => value + 1);
21
202
  const unsubscribe = props.subscribe(bump);
22
203
  const timer = setInterval(bump, everyMs);
23
- onCleanup(() => {
204
+ onCleanup2(() => {
24
205
  unsubscribe();
25
206
  clearInterval(timer);
26
207
  });
@@ -56,229 +237,229 @@ function usePanelKeys(props, refresh) {
56
237
  }));
57
238
  }
58
239
  var Frame = (props) => (() => {
59
- var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("text");
60
- _$insertNode(_el$, _el$2);
61
- _$insertNode(_el$, _el$3);
62
- _$setProp(_el$, "flexDirection", "column");
63
- _$setProp(_el$, "padding", 1);
64
- _$setProp(_el$, "gap", 1);
65
- _$insert(_el$2, () => props.title);
66
- _$insert(_el$, () => props.children, _el$3);
67
- _$insertNode(_el$3, _$createTextNode(`esc/q close \xB7 f fullscreen \xB7 r refresh`));
240
+ var _el$ = _$createElement2("box"), _el$2 = _$createElement2("text"), _el$3 = _$createElement2("text");
241
+ _$insertNode2(_el$, _el$2);
242
+ _$insertNode2(_el$, _el$3);
243
+ _$setProp2(_el$, "flexDirection", "column");
244
+ _$setProp2(_el$, "padding", 1);
245
+ _$setProp2(_el$, "gap", 1);
246
+ _$insert2(_el$2, () => props.title);
247
+ _$insert2(_el$, () => props.children, _el$3);
248
+ _$insertNode2(_el$3, _$createTextNode2(`esc/q close \xB7 f fullscreen \xB7 r refresh`));
68
249
  return _el$;
69
250
  })();
70
- var Failed = (props) => _$createComponent(Show, {
251
+ var Failed = (props) => _$createComponent2(Show, {
71
252
  get when() {
72
253
  return props.error();
73
254
  },
74
255
  get children() {
75
- var _el$5 = _$createElement("text"), _el$6 = _$createTextNode(`Could not load: `);
76
- _$insertNode(_el$5, _el$6);
77
- _$insert(_el$5, () => props.error(), null);
256
+ var _el$5 = _$createElement2("text"), _el$6 = _$createTextNode2(`Could not load: `);
257
+ _$insertNode2(_el$5, _el$6);
258
+ _$insert2(_el$5, () => props.error(), null);
78
259
  return _el$5;
79
260
  }
80
261
  });
81
262
  var FactoryPanel = (props) => {
82
263
  const state = usePanelState(props, "factoryState");
83
264
  usePanelKeys(props, state.refresh);
84
- return _$createComponent(Frame, {
265
+ return _$createComponent2(Frame, {
85
266
  title: "Factory dashboard",
86
267
  get children() {
87
- return [_$createComponent(Failed, {
268
+ return [_$createComponent2(Failed, {
88
269
  get error() {
89
270
  return state.error;
90
271
  }
91
- }), _$createComponent(Show, {
272
+ }), _$createComponent2(Show, {
92
273
  get when() {
93
274
  return state.data();
94
275
  },
95
276
  get fallback() {
96
277
  return (() => {
97
- var _el$7 = _$createElement("text");
98
- _$insert(_el$7, () => state.error() ? "" : "Loading factory state\u2026");
278
+ var _el$7 = _$createElement2("text");
279
+ _$insert2(_el$7, () => state.error() ? "" : "Loading factory state\u2026");
99
280
  return _el$7;
100
281
  })();
101
282
  },
102
283
  children: (data) => [(() => {
103
- var _el$8 = _$createElement("text");
104
- _$insert(_el$8, () => data().headline);
284
+ var _el$8 = _$createElement2("text");
285
+ _$insert2(_el$8, () => data().headline);
105
286
  return _el$8;
106
- })(), _$createComponent(Show, {
287
+ })(), _$createComponent2(Show, {
107
288
  get when() {
108
289
  return data().header;
109
290
  },
110
291
  get fallback() {
111
292
  return (() => {
112
- var _el$41 = _$createElement("text"), _el$42 = _$createTextNode(`Stage: `);
113
- _$insertNode(_el$41, _el$42);
114
- _$insert(_el$41, () => data().stage, null);
293
+ var _el$41 = _$createElement2("text"), _el$42 = _$createTextNode2(`Stage: `);
294
+ _$insertNode2(_el$41, _el$42);
295
+ _$insert2(_el$41, () => data().stage, null);
115
296
  return _el$41;
116
297
  })();
117
298
  },
118
299
  get children() {
119
- var _el$9 = _$createElement("text");
120
- _$insert(_el$9, () => data().header);
300
+ var _el$9 = _$createElement2("text");
301
+ _$insert2(_el$9, () => data().header);
121
302
  return _el$9;
122
303
  }
123
- }), _$createComponent(Show, {
304
+ }), _$createComponent2(Show, {
124
305
  get when() {
125
306
  return data().stage !== "NONE";
126
307
  },
127
308
  get children() {
128
- var _el$0 = _$createElement("text"), _el$1 = _$createTextNode(`Spend: $`);
129
- _$insertNode(_el$0, _el$1);
130
- _$insert(_el$0, () => data().spend.usd.toFixed(2), null);
131
- _$insert(_el$0, (() => {
132
- var _c$ = _$memo(() => !!data().spend.ceilingUSD);
309
+ var _el$0 = _$createElement2("text"), _el$1 = _$createTextNode2(`Spend: $`);
310
+ _$insertNode2(_el$0, _el$1);
311
+ _$insert2(_el$0, () => data().spend.usd.toFixed(2), null);
312
+ _$insert2(_el$0, (() => {
313
+ var _c$ = _$memo2(() => !!data().spend.ceilingUSD);
133
314
  return () => _c$() ? ` / $${data().spend.ceilingUSD}` : "";
134
315
  })(), null);
135
- _$insert(_el$0, () => data().spend.estimated ? " (estimated)" : "", null);
316
+ _$insert2(_el$0, () => data().spend.estimated ? " (estimated)" : "", null);
136
317
  return _el$0;
137
318
  }
138
- }), _$createComponent(Show, {
319
+ }), _$createComponent2(Show, {
139
320
  get when() {
140
321
  return data().tree;
141
322
  },
142
323
  get children() {
143
- var _el$10 = _$createElement("text"), _el$11 = _$createTextNode(`Design tree (round `), _el$12 = _$createTextNode(`): `), _el$13 = _$createTextNode(` settled \xB7 `), _el$14 = _$createTextNode(` open \xB7 `), _el$16 = _$createTextNode(` deferred`);
144
- _$insertNode(_el$10, _el$11);
145
- _$insertNode(_el$10, _el$12);
146
- _$insertNode(_el$10, _el$13);
147
- _$insertNode(_el$10, _el$14);
148
- _$insertNode(_el$10, _el$16);
149
- _$insert(_el$10, () => data().tree.round, _el$12);
150
- _$insert(_el$10, () => data().tree.settled, _el$13);
151
- _$insert(_el$10, () => data().tree.open, _el$14);
152
- _$insert(_el$10, () => data().tree.deferred, _el$16);
153
- _$insert(_el$10, (() => {
154
- var _c$2 = _$memo(() => !!data().tree.facts);
324
+ var _el$10 = _$createElement2("text"), _el$11 = _$createTextNode2(`Design tree (round `), _el$12 = _$createTextNode2(`): `), _el$13 = _$createTextNode2(` settled \xB7 `), _el$14 = _$createTextNode2(` open \xB7 `), _el$16 = _$createTextNode2(` deferred`);
325
+ _$insertNode2(_el$10, _el$11);
326
+ _$insertNode2(_el$10, _el$12);
327
+ _$insertNode2(_el$10, _el$13);
328
+ _$insertNode2(_el$10, _el$14);
329
+ _$insertNode2(_el$10, _el$16);
330
+ _$insert2(_el$10, () => data().tree.round, _el$12);
331
+ _$insert2(_el$10, () => data().tree.settled, _el$13);
332
+ _$insert2(_el$10, () => data().tree.open, _el$14);
333
+ _$insert2(_el$10, () => data().tree.deferred, _el$16);
334
+ _$insert2(_el$10, (() => {
335
+ var _c$2 = _$memo2(() => !!data().tree.facts);
155
336
  return () => _c$2() ? ` (${data().tree.facts} for research)` : "";
156
337
  })(), null);
157
338
  return _el$10;
158
339
  }
159
- }), _$createComponent(Show, {
340
+ }), _$createComponent2(Show, {
160
341
  get when() {
161
342
  return data().paused;
162
343
  },
163
344
  get children() {
164
- var _el$17 = _$createElement("text"), _el$18 = _$createTextNode(`\u23F8 `);
165
- _$insertNode(_el$17, _el$18);
166
- _$insert(_el$17, () => data().paused, null);
345
+ var _el$17 = _$createElement2("text"), _el$18 = _$createTextNode2(`\u23F8 `);
346
+ _$insertNode2(_el$17, _el$18);
347
+ _$insert2(_el$17, () => data().paused, null);
167
348
  return _el$17;
168
349
  }
169
- }), _$createComponent(Show, {
350
+ }), _$createComponent2(Show, {
170
351
  get when() {
171
352
  return data().halt;
172
353
  },
173
354
  get children() {
174
- var _el$19 = _$createElement("text"), _el$20 = _$createTextNode(`HALTED: `);
175
- _$insertNode(_el$19, _el$20);
176
- _$insert(_el$19, () => data().halt, null);
355
+ var _el$19 = _$createElement2("text"), _el$20 = _$createTextNode2(`HALTED: `);
356
+ _$insertNode2(_el$19, _el$20);
357
+ _$insert2(_el$19, () => data().halt, null);
177
358
  return _el$19;
178
359
  }
179
- }), _$createComponent(Show, {
360
+ }), _$createComponent2(Show, {
180
361
  get when() {
181
362
  return data().pending.length;
182
363
  },
183
364
  get children() {
184
- var _el$21 = _$createElement("text"), _el$22 = _$createTextNode(`Waiting on you: approve `), _el$23 = _$createTextNode(`: run \`es approve `), _el$24 = _$createTextNode(`\` in a terminal (/es-approve previews it)`);
185
- _$insertNode(_el$21, _el$22);
186
- _$insertNode(_el$21, _el$23);
187
- _$insertNode(_el$21, _el$24);
188
- _$insert(_el$21, () => data().pending.join(", "), _el$23);
189
- _$insert(_el$21, () => data().pending[0], _el$24);
365
+ var _el$21 = _$createElement2("text"), _el$22 = _$createTextNode2(`Waiting on you: approve `), _el$23 = _$createTextNode2(` with /es-approve (or \`es approve `), _el$24 = _$createTextNode2(`\`)`);
366
+ _$insertNode2(_el$21, _el$22);
367
+ _$insertNode2(_el$21, _el$23);
368
+ _$insertNode2(_el$21, _el$24);
369
+ _$insert2(_el$21, () => data().pending.join(", "), _el$23);
370
+ _$insert2(_el$21, () => data().pending[0], _el$24);
190
371
  return _el$21;
191
372
  }
192
- }), _$createComponent(Show, {
373
+ }), _$createComponent2(Show, {
193
374
  get when() {
194
375
  return data().seats.length;
195
376
  },
196
377
  get children() {
197
- var _el$25 = _$createElement("box"), _el$26 = _$createElement("text");
198
- _$insertNode(_el$25, _el$26);
199
- _$setProp(_el$25, "flexDirection", "column");
200
- _$insertNode(_el$26, _$createTextNode(`Seats:`));
201
- _$insert(_el$25, _$createComponent(For, {
378
+ var _el$25 = _$createElement2("box"), _el$26 = _$createElement2("text");
379
+ _$insertNode2(_el$25, _el$26);
380
+ _$setProp2(_el$25, "flexDirection", "column");
381
+ _$insertNode2(_el$26, _$createTextNode2(`Seats:`));
382
+ _$insert2(_el$25, _$createComponent2(For, {
202
383
  get each() {
203
384
  return data().seats;
204
385
  },
205
386
  children: (line) => (() => {
206
- var _el$43 = _$createElement("text");
207
- _$insert(_el$43, ` ${line}`);
387
+ var _el$43 = _$createElement2("text");
388
+ _$insert2(_el$43, ` ${line}`);
208
389
  return _el$43;
209
390
  })()
210
391
  }), null);
211
392
  return _el$25;
212
393
  }
213
- }), _$createComponent(Show, {
394
+ }), _$createComponent2(Show, {
214
395
  get when() {
215
396
  return data().research;
216
397
  },
217
398
  get children() {
218
- var _el$28 = _$createElement("text"), _el$29 = _$createTextNode(`Research: `);
219
- _$insertNode(_el$28, _el$29);
220
- _$insert(_el$28, () => data().research, null);
399
+ var _el$28 = _$createElement2("text"), _el$29 = _$createTextNode2(`Research: `);
400
+ _$insertNode2(_el$28, _el$29);
401
+ _$insert2(_el$28, () => data().research, null);
221
402
  return _el$28;
222
403
  }
223
- }), _$createComponent(Show, {
404
+ }), _$createComponent2(Show, {
224
405
  get when() {
225
406
  return data().phases.length;
226
407
  },
227
408
  get children() {
228
- var _el$30 = _$createElement("box"), _el$31 = _$createElement("text");
229
- _$insertNode(_el$30, _el$31);
230
- _$setProp(_el$30, "flexDirection", "column");
231
- _$insertNode(_el$31, _$createTextNode(`Phases:`));
232
- _$insert(_el$30, _$createComponent(For, {
409
+ var _el$30 = _$createElement2("box"), _el$31 = _$createElement2("text");
410
+ _$insertNode2(_el$30, _el$31);
411
+ _$setProp2(_el$30, "flexDirection", "column");
412
+ _$insertNode2(_el$31, _$createTextNode2(`Phases:`));
413
+ _$insert2(_el$30, _$createComponent2(For, {
233
414
  get each() {
234
415
  return data().phases;
235
416
  },
236
417
  children: (phase) => (() => {
237
- var _el$44 = _$createElement("text"), _el$45 = _$createTextNode(` \xB7 `), _el$46 = _$createTextNode(` \xB7 failures `);
238
- _$insertNode(_el$44, _el$45);
239
- _$insertNode(_el$44, _el$46);
240
- _$insert(_el$44, () => phase.id === data().activePhase ? "\u25B6 " : " ", _el$45);
241
- _$insert(_el$44, () => phase.id, _el$45);
242
- _$insert(_el$44, (() => {
243
- var _c$3 = _$memo(() => !!phase.title);
418
+ var _el$44 = _$createElement2("text"), _el$45 = _$createTextNode2(` \xB7 `), _el$46 = _$createTextNode2(` \xB7 failures `);
419
+ _$insertNode2(_el$44, _el$45);
420
+ _$insertNode2(_el$44, _el$46);
421
+ _$insert2(_el$44, () => phase.id === data().activePhase ? "\u25B6 " : " ", _el$45);
422
+ _$insert2(_el$44, () => phase.id, _el$45);
423
+ _$insert2(_el$44, (() => {
424
+ var _c$3 = _$memo2(() => !!phase.title);
244
425
  return () => _c$3() ? ` ${phase.title}` : "";
245
426
  })(), _el$45);
246
- _$insert(_el$44, () => phase.status, _el$46);
247
- _$insert(_el$44, () => phase.failures, null);
427
+ _$insert2(_el$44, () => phase.status, _el$46);
428
+ _$insert2(_el$44, () => phase.failures, null);
248
429
  return _el$44;
249
430
  })()
250
431
  }), null);
251
432
  return _el$30;
252
433
  }
253
- }), _$createComponent(Show, {
434
+ }), _$createComponent2(Show, {
254
435
  get when() {
255
436
  return data().audits?.length;
256
437
  },
257
438
  get children() {
258
- var _el$33 = _$createElement("box"), _el$34 = _$createElement("text");
259
- _$insertNode(_el$33, _el$34);
260
- _$setProp(_el$33, "flexDirection", "column");
261
- _$insertNode(_el$34, _$createTextNode(`Audits:`));
262
- _$insert(_el$33, _$createComponent(For, {
439
+ var _el$33 = _$createElement2("box"), _el$34 = _$createElement2("text");
440
+ _$insertNode2(_el$33, _el$34);
441
+ _$setProp2(_el$33, "flexDirection", "column");
442
+ _$insertNode2(_el$34, _$createTextNode2(`Audits:`));
443
+ _$insert2(_el$33, _$createComponent2(For, {
263
444
  get each() {
264
445
  return data().audits;
265
446
  },
266
447
  children: (audit) => (() => {
267
- var _el$47 = _$createElement("text"), _el$48 = _$createTextNode(` `), _el$49 = _$createTextNode(` \xB7 `), _el$50 = _$createTextNode(` \xB7 `), _el$51 = _$createTextNode(` r`), _el$52 = _$createTextNode(` \xB7 t:`), _el$53 = _$createTextNode(` a:`);
268
- _$insertNode(_el$47, _el$48);
269
- _$insertNode(_el$47, _el$49);
270
- _$insertNode(_el$47, _el$50);
271
- _$insertNode(_el$47, _el$51);
272
- _$insertNode(_el$47, _el$52);
273
- _$insertNode(_el$47, _el$53);
274
- _$insert(_el$47, () => audit.id, _el$49);
275
- _$insert(_el$47, () => audit.target, _el$50);
276
- _$insert(_el$47, () => audit.status, _el$51);
277
- _$insert(_el$47, () => audit.round, _el$52);
278
- _$insert(_el$47, () => audit.thesis, _el$53);
279
- _$insert(_el$47, () => audit.antithesis, null);
280
- _$insert(_el$47, (() => {
281
- var _c$4 = _$memo(() => !!audit.tiebreak);
448
+ var _el$47 = _$createElement2("text"), _el$48 = _$createTextNode2(` `), _el$49 = _$createTextNode2(` \xB7 `), _el$50 = _$createTextNode2(` \xB7 `), _el$51 = _$createTextNode2(` r`), _el$52 = _$createTextNode2(` \xB7 t:`), _el$53 = _$createTextNode2(` a:`);
449
+ _$insertNode2(_el$47, _el$48);
450
+ _$insertNode2(_el$47, _el$49);
451
+ _$insertNode2(_el$47, _el$50);
452
+ _$insertNode2(_el$47, _el$51);
453
+ _$insertNode2(_el$47, _el$52);
454
+ _$insertNode2(_el$47, _el$53);
455
+ _$insert2(_el$47, () => audit.id, _el$49);
456
+ _$insert2(_el$47, () => audit.target, _el$50);
457
+ _$insert2(_el$47, () => audit.status, _el$51);
458
+ _$insert2(_el$47, () => audit.round, _el$52);
459
+ _$insert2(_el$47, () => audit.thesis, _el$53);
460
+ _$insert2(_el$47, () => audit.antithesis, null);
461
+ _$insert2(_el$47, (() => {
462
+ var _c$4 = _$memo2(() => !!audit.tiebreak);
282
463
  return () => _c$4() ? ` x:${audit.tiebreak}` : "";
283
464
  })(), null);
284
465
  return _el$47;
@@ -286,35 +467,35 @@ var FactoryPanel = (props) => {
286
467
  }), null);
287
468
  return _el$33;
288
469
  }
289
- }), _$createComponent(Show, {
470
+ }), _$createComponent2(Show, {
290
471
  get when() {
291
472
  return data().events.length;
292
473
  },
293
474
  get children() {
294
- var _el$36 = _$createElement("box"), _el$37 = _$createElement("text");
295
- _$insertNode(_el$36, _el$37);
296
- _$setProp(_el$36, "flexDirection", "column");
297
- _$insertNode(_el$37, _$createTextNode(`Recent events:`));
298
- _$insert(_el$36, _$createComponent(For, {
475
+ var _el$36 = _$createElement2("box"), _el$37 = _$createElement2("text");
476
+ _$insertNode2(_el$36, _el$37);
477
+ _$setProp2(_el$36, "flexDirection", "column");
478
+ _$insertNode2(_el$37, _$createTextNode2(`Recent events:`));
479
+ _$insert2(_el$36, _$createComponent2(For, {
299
480
  get each() {
300
481
  return data().events;
301
482
  },
302
483
  children: (line) => (() => {
303
- var _el$54 = _$createElement("text");
304
- _$insert(_el$54, ` ${line}`);
484
+ var _el$54 = _$createElement2("text");
485
+ _$insert2(_el$54, ` ${line}`);
305
486
  return _el$54;
306
487
  })()
307
488
  }), null);
308
489
  return _el$36;
309
490
  }
310
- }), _$createComponent(Show, {
491
+ }), _$createComponent2(Show, {
311
492
  get when() {
312
493
  return data().release;
313
494
  },
314
495
  get children() {
315
- var _el$39 = _$createElement("text"), _el$40 = _$createTextNode(`PR: `);
316
- _$insertNode(_el$39, _el$40);
317
- _$insert(_el$39, () => data().release, null);
496
+ var _el$39 = _$createElement2("text"), _el$40 = _$createTextNode2(`PR: `);
497
+ _$insertNode2(_el$39, _el$40);
498
+ _$insert2(_el$39, () => data().release, null);
318
499
  return _el$39;
319
500
  }
320
501
  })]
@@ -325,55 +506,55 @@ var FactoryPanel = (props) => {
325
506
  var LspPanel = (props) => {
326
507
  const state = usePanelState(props, "lspState");
327
508
  usePanelKeys(props, state.refresh);
328
- return _$createComponent(Frame, {
509
+ return _$createComponent2(Frame, {
329
510
  title: "Language servers",
330
511
  get children() {
331
- return [_$createComponent(Failed, {
512
+ return [_$createComponent2(Failed, {
332
513
  get error() {
333
514
  return state.error;
334
515
  }
335
- }), _$createComponent(Show, {
516
+ }), _$createComponent2(Show, {
336
517
  get when() {
337
518
  return state.data();
338
519
  },
339
520
  get fallback() {
340
521
  return (() => {
341
- var _el$55 = _$createElement("text");
342
- _$insert(_el$55, () => state.error() ? "" : "Loading language servers\u2026");
522
+ var _el$55 = _$createElement2("text");
523
+ _$insert2(_el$55, () => state.error() ? "" : "Loading language servers\u2026");
343
524
  return _el$55;
344
525
  })();
345
526
  },
346
527
  children: (data) => [(() => {
347
- var _el$56 = _$createElement("text");
348
- _$insert(_el$56, () => data().enabled ? "LSP is on." : "LSP is disabled (lsp: false).");
528
+ var _el$56 = _$createElement2("text");
529
+ _$insert2(_el$56, () => data().enabled ? "LSP is on." : "LSP is disabled (lsp: false).");
349
530
  return _el$56;
350
- })(), _$createComponent(For, {
531
+ })(), _$createComponent2(For, {
351
532
  get each() {
352
533
  return data().servers;
353
534
  },
354
535
  children: (server) => (() => {
355
- var _el$57 = _$createElement("text"), _el$58 = _$createTextNode(` `), _el$59 = _$createTextNode(` [`), _el$60 = _$createTextNode(`]`);
356
- _$insertNode(_el$57, _el$58);
357
- _$insertNode(_el$57, _el$59);
358
- _$insertNode(_el$57, _el$60);
359
- _$insert(_el$57, () => server.available ? "\u25CF" : "\u25CB", _el$58);
360
- _$insert(_el$57, () => server.id, _el$59);
361
- _$insert(_el$57, () => server.extensions.join(" "), _el$60);
362
- _$insert(_el$57, (() => {
363
- var _c$5 = _$memo(() => !!server.running);
536
+ var _el$57 = _$createElement2("text"), _el$58 = _$createTextNode2(` `), _el$59 = _$createTextNode2(` [`), _el$60 = _$createTextNode2(`]`);
537
+ _$insertNode2(_el$57, _el$58);
538
+ _$insertNode2(_el$57, _el$59);
539
+ _$insertNode2(_el$57, _el$60);
540
+ _$insert2(_el$57, () => server.available ? "\u25CF" : "\u25CB", _el$58);
541
+ _$insert2(_el$57, () => server.id, _el$59);
542
+ _$insert2(_el$57, () => server.extensions.join(" "), _el$60);
543
+ _$insert2(_el$57, (() => {
544
+ var _c$5 = _$memo2(() => !!server.running);
364
545
  return () => _c$5() ? ` \xB7 ${server.running} running` : "";
365
546
  })(), null);
366
- _$insert(_el$57, () => server.available ? "" : " \u2014 not installed", null);
547
+ _$insert2(_el$57, () => server.available ? "" : " \u2014 not installed", null);
367
548
  return _el$57;
368
549
  })()
369
- }), _$createComponent(For, {
550
+ }), _$createComponent2(For, {
370
551
  get each() {
371
552
  return data().diagnostics;
372
553
  },
373
554
  children: (diagnostic) => (() => {
374
- var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(`! `);
375
- _$insertNode(_el$61, _el$62);
376
- _$insert(_el$61, diagnostic, null);
555
+ var _el$61 = _$createElement2("text"), _el$62 = _$createTextNode2(`! `);
556
+ _$insertNode2(_el$61, _el$62);
557
+ _$insert2(_el$61, diagnostic, null);
377
558
  return _el$61;
378
559
  })()
379
560
  })]
@@ -384,89 +565,89 @@ var LspPanel = (props) => {
384
565
  var HooksPanel = (props) => {
385
566
  const state = usePanelState(props, "hooksState");
386
567
  usePanelKeys(props, state.refresh);
387
- return _$createComponent(Frame, {
568
+ return _$createComponent2(Frame, {
388
569
  title: "Hook bridge",
389
570
  get children() {
390
- return [_$createComponent(Failed, {
571
+ return [_$createComponent2(Failed, {
391
572
  get error() {
392
573
  return state.error;
393
574
  }
394
- }), _$createComponent(Show, {
575
+ }), _$createComponent2(Show, {
395
576
  get when() {
396
577
  return state.data();
397
578
  },
398
579
  get fallback() {
399
580
  return (() => {
400
- var _el$63 = _$createElement("text");
401
- _$insert(_el$63, () => state.error() ? "" : "Loading hooks\u2026");
581
+ var _el$63 = _$createElement2("text");
582
+ _$insert2(_el$63, () => state.error() ? "" : "Loading hooks\u2026");
402
583
  return _el$63;
403
584
  })();
404
585
  },
405
586
  children: (data) => [(() => {
406
- var _el$64 = _$createElement("text"), _el$65 = _$createTextNode(` handler(s) \xB7 `), _el$66 = _$createTextNode(` from the project \xB7 `);
407
- _$insertNode(_el$64, _el$65);
408
- _$insertNode(_el$64, _el$66);
409
- _$insert(_el$64, () => data().handlers, _el$65);
410
- _$insert(_el$64, () => data().projectHandlers, _el$66);
411
- _$insert(_el$64, (() => {
412
- var _c$6 = _$memo(() => data().projectHandlers === 0);
587
+ var _el$64 = _$createElement2("text"), _el$65 = _$createTextNode2(` handler(s) \xB7 `), _el$66 = _$createTextNode2(` from the project \xB7 `);
588
+ _$insertNode2(_el$64, _el$65);
589
+ _$insertNode2(_el$64, _el$66);
590
+ _$insert2(_el$64, () => data().handlers, _el$65);
591
+ _$insert2(_el$64, () => data().projectHandlers, _el$66);
592
+ _$insert2(_el$64, (() => {
593
+ var _c$6 = _$memo2(() => data().projectHandlers === 0);
413
594
  return () => _c$6() ? "nothing to trust" : data().trusted ? "trusted" : "NOT trusted";
414
595
  })(), null);
415
596
  return _el$64;
416
- })(), _$createComponent(For, {
597
+ })(), _$createComponent2(For, {
417
598
  get each() {
418
599
  return data().projectLines;
419
600
  },
420
601
  children: (line) => (() => {
421
- var _el$70 = _$createElement("text");
422
- _$insert(_el$70, line);
602
+ var _el$70 = _$createElement2("text");
603
+ _$insert2(_el$70, line);
423
604
  return _el$70;
424
605
  })()
425
- }), _$createComponent(Show, {
606
+ }), _$createComponent2(Show, {
426
607
  get when() {
427
608
  return data().loss.length;
428
609
  },
429
610
  get children() {
430
611
  return [(() => {
431
- var _el$68 = _$createElement("text");
432
- _$insertNode(_el$68, _$createTextNode(`Capability loss (advisory rows):`));
612
+ var _el$68 = _$createElement2("text");
613
+ _$insertNode2(_el$68, _$createTextNode2(`Capability loss (advisory rows):`));
433
614
  return _el$68;
434
- })(), _$createComponent(For, {
615
+ })(), _$createComponent2(For, {
435
616
  get each() {
436
617
  return data().loss;
437
618
  },
438
619
  children: (item) => (() => {
439
- var _el$71 = _$createElement("text"), _el$72 = _$createTextNode(`! `), _el$73 = _$createTextNode(` \xB7 `), _el$74 = _$createTextNode(` \u2014 `), _el$75 = _$createTextNode(`: `);
440
- _$insertNode(_el$71, _el$72);
441
- _$insertNode(_el$71, _el$73);
442
- _$insertNode(_el$71, _el$74);
443
- _$insertNode(_el$71, _el$75);
444
- _$insert(_el$71, () => item.event, _el$73);
445
- _$insert(_el$71, () => item.handler, _el$74);
446
- _$insert(_el$71, () => item.support, _el$75);
447
- _$insert(_el$71, () => item.reason, null);
620
+ var _el$71 = _$createElement2("text"), _el$72 = _$createTextNode2(`! `), _el$73 = _$createTextNode2(` \xB7 `), _el$74 = _$createTextNode2(` \u2014 `), _el$75 = _$createTextNode2(`: `);
621
+ _$insertNode2(_el$71, _el$72);
622
+ _$insertNode2(_el$71, _el$73);
623
+ _$insertNode2(_el$71, _el$74);
624
+ _$insertNode2(_el$71, _el$75);
625
+ _$insert2(_el$71, () => item.event, _el$73);
626
+ _$insert2(_el$71, () => item.handler, _el$74);
627
+ _$insert2(_el$71, () => item.support, _el$75);
628
+ _$insert2(_el$71, () => item.reason, null);
448
629
  return _el$71;
449
630
  })()
450
631
  })];
451
632
  }
452
- }), _$createComponent(For, {
633
+ }), _$createComponent2(For, {
453
634
  get each() {
454
635
  return data().diagnostics;
455
636
  },
456
637
  children: (item) => (() => {
457
- var _el$76 = _$createElement("text"), _el$77 = _$createTextNode(`! `);
458
- _$insertNode(_el$76, _el$77);
459
- _$insert(_el$76, item, null);
638
+ var _el$76 = _$createElement2("text"), _el$77 = _$createTextNode2(`! `);
639
+ _$insertNode2(_el$76, _el$77);
640
+ _$insert2(_el$76, item, null);
460
641
  return _el$76;
461
642
  })()
462
- }), _$createComponent(For, {
643
+ }), _$createComponent2(For, {
463
644
  get each() {
464
645
  return data().recent;
465
646
  },
466
647
  children: (item) => (() => {
467
- var _el$78 = _$createElement("text"), _el$79 = _$createTextNode(`recent error: `);
468
- _$insertNode(_el$78, _el$79);
469
- _$insert(_el$78, item, null);
648
+ var _el$78 = _$createElement2("text"), _el$79 = _$createTextNode2(`recent error: `);
649
+ _$insertNode2(_el$78, _el$79);
650
+ _$insert2(_el$78, item, null);
470
651
  return _el$78;
471
652
  })()
472
653
  })]
@@ -477,90 +658,105 @@ var HooksPanel = (props) => {
477
658
  var BrainstormPanel = (props) => {
478
659
  const state = usePanelState(props, "brainstormState");
479
660
  usePanelKeys(props, state.refresh);
480
- return _$createComponent(Frame, {
661
+ return _$createComponent2(Frame, {
481
662
  title: "Brainstorm board",
482
663
  get children() {
483
- return [_$createComponent(Failed, {
664
+ return [_$createComponent2(Failed, {
484
665
  get error() {
485
666
  return state.error;
486
667
  }
487
- }), _$createComponent(Show, {
668
+ }), _$createComponent2(Show, {
488
669
  get when() {
489
670
  return state.data();
490
671
  },
491
672
  get fallback() {
492
673
  return (() => {
493
- var _el$80 = _$createElement("text");
494
- _$insert(_el$80, () => state.error() ? "" : "Loading brainstorm\u2026");
674
+ var _el$80 = _$createElement2("text");
675
+ _$insert2(_el$80, () => state.error() ? "" : "Loading brainstorm\u2026");
495
676
  return _el$80;
496
677
  })();
497
678
  },
498
- children: (data) => _$createComponent(Show, {
679
+ children: (data) => _$createComponent2(Show, {
499
680
  get when() {
500
681
  return data().active;
501
682
  },
502
683
  get fallback() {
503
684
  return (() => {
504
- var _el$95 = _$createElement("text");
505
- _$insertNode(_el$95, _$createTextNode(`No brainstorm in .factory/brainstorm yet. Run /brainstorm.`));
506
- return _el$95;
685
+ var _el$100 = _$createElement2("text");
686
+ _$insertNode2(_el$100, _$createTextNode2(`No brainstorm in .factory/brainstorm yet. Run /brainstorm.`));
687
+ return _el$100;
507
688
  })();
508
689
  },
509
690
  get children() {
510
691
  return [(() => {
511
- var _el$81 = _$createElement("text"), _el$82 = _$createTextNode(`Brief: `);
512
- _$insertNode(_el$81, _el$82);
513
- _$insert(_el$81, () => data().brief, null);
692
+ var _el$81 = _$createElement2("text"), _el$82 = _$createTextNode2(`Brief: `);
693
+ _$insertNode2(_el$81, _el$82);
694
+ _$insert2(_el$81, () => data().brief, null);
514
695
  return _el$81;
515
- })(), (() => {
516
- var _el$83 = _$createElement("text"), _el$84 = _$createTextNode(` idea(s) \xB7 `), _el$85 = _$createTextNode(` duplicate(s) \xB7 `), _el$86 = _$createTextNode(` scored \xB7 `);
517
- _$insertNode(_el$83, _el$84);
518
- _$insertNode(_el$83, _el$85);
519
- _$insertNode(_el$83, _el$86);
520
- _$insert(_el$83, () => data().ideas, _el$84);
521
- _$insert(_el$83, () => data().duplicates, _el$85);
522
- _$insert(_el$83, () => data().scored, _el$86);
523
- _$insert(_el$83, () => data().complete ? "complete" : "in progress", null);
524
- return _el$83;
525
- })(), (() => {
526
- var _el$88 = _$createElement("text"), _el$89 = _$createTextNode(`Coverage: `);
527
- _$insertNode(_el$88, _el$89);
528
- _$insert(_el$88, () => data().lenses.map((lens) => `${lens} ${data().coverage[lens] ?? 0}`).join(" \xB7 "), null);
696
+ })(), _$createComponent2(Show, {
697
+ get when() {
698
+ return data().runs?.length > 1;
699
+ },
700
+ get children() {
701
+ var _el$83 = _$createElement2("text"), _el$84 = _$createTextNode2(`Run `), _el$85 = _$createTextNode2(` (`), _el$86 = _$createTextNode2(` runs: `), _el$87 = _$createTextNode2(` \u2014 \`es brainstorm show [run]\`)`);
702
+ _$insertNode2(_el$83, _el$84);
703
+ _$insertNode2(_el$83, _el$85);
704
+ _$insertNode2(_el$83, _el$86);
705
+ _$insertNode2(_el$83, _el$87);
706
+ _$insert2(_el$83, () => data().run, _el$85);
707
+ _$insert2(_el$83, () => data().runs.length, _el$86);
708
+ _$insert2(_el$83, () => data().runs.join(", "), _el$87);
709
+ return _el$83;
710
+ }
711
+ }), (() => {
712
+ var _el$88 = _$createElement2("text"), _el$89 = _$createTextNode2(` idea(s) \xB7 `), _el$90 = _$createTextNode2(` duplicate(s) \xB7 `), _el$91 = _$createTextNode2(` scored \xB7 `);
713
+ _$insertNode2(_el$88, _el$89);
714
+ _$insertNode2(_el$88, _el$90);
715
+ _$insertNode2(_el$88, _el$91);
716
+ _$insert2(_el$88, () => data().ideas, _el$89);
717
+ _$insert2(_el$88, () => data().duplicates, _el$90);
718
+ _$insert2(_el$88, () => data().scored, _el$91);
719
+ _$insert2(_el$88, () => data().complete ? "complete" : "in progress", null);
529
720
  return _el$88;
530
- })(), _$createComponent(Show, {
721
+ })(), (() => {
722
+ var _el$93 = _$createElement2("text"), _el$94 = _$createTextNode2(`Coverage: `);
723
+ _$insertNode2(_el$93, _el$94);
724
+ _$insert2(_el$93, () => data().lenses.map((lens) => `${lens} ${data().coverage[lens] ?? 0}`).join(" \xB7 "), null);
725
+ return _el$93;
726
+ })(), _$createComponent2(Show, {
531
727
  get when() {
532
728
  return data().gaps.length;
533
729
  },
534
730
  get children() {
535
- var _el$91 = _$createElement("text"), _el$92 = _$createTextNode(`Gaps: `);
536
- _$insertNode(_el$91, _el$92);
537
- _$insert(_el$91, () => data().gaps.join(", "), null);
538
- return _el$91;
731
+ var _el$96 = _$createElement2("text"), _el$97 = _$createTextNode2(`Gaps: `);
732
+ _$insertNode2(_el$96, _el$97);
733
+ _$insert2(_el$96, () => data().gaps.join(", "), null);
734
+ return _el$96;
539
735
  }
540
- }), _$createComponent(Show, {
736
+ }), _$createComponent2(Show, {
541
737
  get when() {
542
738
  return data().shortlist.length;
543
739
  },
544
740
  get children() {
545
741
  return [(() => {
546
- var _el$93 = _$createElement("text");
547
- _$insertNode(_el$93, _$createTextNode(`Shortlist:`));
548
- return _el$93;
549
- })(), _$createComponent(For, {
742
+ var _el$98 = _$createElement2("text");
743
+ _$insertNode2(_el$98, _$createTextNode2(`Shortlist:`));
744
+ return _el$98;
745
+ })(), _$createComponent2(For, {
550
746
  get each() {
551
747
  return data().shortlist;
552
748
  },
553
749
  children: (entry) => (() => {
554
- var _el$97 = _$createElement("text"), _el$98 = _$createTextNode(` `), _el$99 = _$createTextNode(` (`), _el$100 = _$createTextNode(`/20) \u2014 `);
555
- _$insertNode(_el$97, _el$98);
556
- _$insertNode(_el$97, _el$99);
557
- _$insertNode(_el$97, _el$100);
558
- _$insert(_el$97, () => entry.outlier ? "\u25C7" : "\u25C6", _el$98);
559
- _$insert(_el$97, () => entry.id, _el$99);
560
- _$insert(_el$97, () => entry.total, _el$100);
561
- _$insert(_el$97, () => entry.title, null);
562
- _$insert(_el$97, () => entry.outlier ? " (forced outlier)" : "", null);
563
- return _el$97;
750
+ var _el$102 = _$createElement2("text"), _el$103 = _$createTextNode2(` `), _el$104 = _$createTextNode2(` (`), _el$105 = _$createTextNode2(`/20) \u2014 `);
751
+ _$insertNode2(_el$102, _el$103);
752
+ _$insertNode2(_el$102, _el$104);
753
+ _$insertNode2(_el$102, _el$105);
754
+ _$insert2(_el$102, () => entry.outlier ? "\u25C7" : "\u25C6", _el$103);
755
+ _$insert2(_el$102, () => entry.id, _el$104);
756
+ _$insert2(_el$102, () => entry.total, _el$105);
757
+ _$insert2(_el$102, () => entry.title, null);
758
+ _$insert2(_el$102, () => entry.outlier ? " (forced outlier)" : "", null);
759
+ return _el$102;
564
760
  })()
565
761
  })];
566
762
  }
@@ -579,14 +775,14 @@ var PANEL_COMPONENTS = {
579
775
  };
580
776
  var FactoryFooter = (props) => {
581
777
  const state = usePanelState(props, "status", FOOTER_REFRESH_MS);
582
- return _$createComponent(Show, {
778
+ return _$createComponent2(Show, {
583
779
  get when() {
584
780
  return state.data()?.footer;
585
781
  },
586
782
  get children() {
587
- var _el$101 = _$createElement("text");
588
- _$insert(_el$101, () => state.data().footer);
589
- return _el$101;
783
+ var _el$106 = _$createElement2("text");
784
+ _$insert2(_el$106, () => state.data().footer);
785
+ return _el$106;
590
786
  }
591
787
  });
592
788
  };
@@ -604,7 +800,7 @@ function registerPanels(context, call, subscribe) {
604
800
  const layer = typeof context.keymap?.layer === "function" ? (factory) => context.keymap.layer(factory) : undefined;
605
801
  const disposers = [];
606
802
  for (const [name, Panel] of Object.entries(PANEL_COMPONENTS)) {
607
- const dispose = claimSlot(context, "session.panel", (input) => input.name === name ? _$createComponent(Panel, _$mergeProps({
803
+ const dispose = claimSlot(context, "session.panel", (input) => input.name === name ? _$createComponent2(Panel, _$mergeProps({
608
804
  call,
609
805
  subscribe
610
806
  }, () => input.close && input.toggleFullscreen ? {
@@ -618,7 +814,7 @@ function registerPanels(context, call, subscribe) {
618
814
  if (dispose)
619
815
  disposers.push(dispose);
620
816
  }
621
- const footer = claimSlot(context, "prompt.footer.status", () => _$createComponent(FactoryFooter, {
817
+ const footer = claimSlot(context, "prompt.footer.status", () => _$createComponent2(FactoryFooter, {
622
818
  call,
623
819
  subscribe
624
820
  }));
@@ -647,12 +843,16 @@ var obj = (properties, required = []) => ({
647
843
  });
648
844
  var str = { type: "string" };
649
845
  var strArray = { type: "array", items: str };
650
- var Preview = obj({ ok: { type: "boolean" }, title: str, lines: strArray, problems: strArray, token: str }, [
651
- "ok",
652
- "title",
653
- "lines",
654
- "problems"
655
- ]);
846
+ var num = { type: "number" };
847
+ var Preview = obj({
848
+ ok: { type: "boolean" },
849
+ title: str,
850
+ lines: strArray,
851
+ problems: strArray,
852
+ token: str,
853
+ subjectHash: str,
854
+ issuedAt: num
855
+ }, ["ok", "title", "lines", "problems"]);
656
856
  var EsRpc = define({
657
857
  id: "epistemic-swarm",
658
858
  methods: {
@@ -673,6 +873,15 @@ var EsRpc = define({
673
873
  input: obj({ stage: { type: "string", enum: ["frontier", "spec"] } }, ["stage"]),
674
874
  output: Preview
675
875
  },
876
+ redeemApproval: {
877
+ input: obj({ stage: { type: "string", enum: ["frontier", "spec"] }, token: str, subjectHash: str }, [
878
+ "stage",
879
+ "token",
880
+ "subjectHash"
881
+ ]),
882
+ output: obj({ ok: { type: "boolean" } }, ["ok"]),
883
+ errors: { refused: obj({ reason: str }, ["reason"]) }
884
+ },
676
885
  previewTrust: { input: obj({}), output: Preview },
677
886
  previewResume: { input: obj({}), output: Preview },
678
887
  previewLspInstall: { input: obj({ id: str }, ["id"]), output: Preview },
@@ -759,7 +968,7 @@ var tui_default = Plugin.define({
759
968
  location: location()
760
969
  });
761
970
  const stopPanels = registerPanels(context, call, (listener) => rpc.events.on("changed", () => listener()));
762
- const user = userInfo().username;
971
+ const user = userInfo2().username;
763
972
  const toast = (message, variant = "info") => context.ui.toast.show({
764
973
  title: "Epistemic Swarm",
765
974
  message,
@@ -818,13 +1027,50 @@ var tui_default = Plugin.define({
818
1027
  const token = await confirm(preview, "Approve");
819
1028
  if (!token)
820
1029
  return;
821
- await context.ui.dialog.alert({
1030
+ const terminalAlert = () => context.ui.dialog.alert({
822
1031
  title: preview.title,
823
1032
  message: `${preview.lines.join(`
824
1033
  `)}
825
1034
 
826
- Run \`es approve ${stage}\` at a terminal with your passphrase (1.1.1: approvals need the sealed human key).`
1035
+ Run \`es approve ${stage}\` at a terminal with your passphrase (approvals need the sealed human key).`
1036
+ });
1037
+ if (!preview.subjectHash) {
1038
+ await terminalAlert();
1039
+ return;
1040
+ }
1041
+ const outcome = await approveInTui({
1042
+ root: location().directory,
1043
+ stage,
1044
+ expectedSubjectHash: preview.subjectHash,
1045
+ ...token ? {
1046
+ previewToken: token
1047
+ } : {},
1048
+ ...preview.issuedAt !== undefined ? {
1049
+ previewIssuedAt: preview.issuedAt
1050
+ } : {},
1051
+ redeemPreview: (previewToken) => call("redeemApproval", {
1052
+ stage,
1053
+ token: previewToken,
1054
+ subjectHash: preview.subjectHash
1055
+ }),
1056
+ approvedBy: user,
1057
+ readPassphrase: (title) => readMaskedPassphrase(context.ui.dialog, title)
827
1058
  });
1059
+ if (outcome.ok) {
1060
+ toast(`Approved ${stage} as ${outcome.record.approvedBy} (${outcome.record.subject.length} artifact(s)).`, "success");
1061
+ return;
1062
+ }
1063
+ if ("fallback" in outcome) {
1064
+ await terminalAlert();
1065
+ return;
1066
+ }
1067
+ if ("locked" in outcome) {
1068
+ await context.ui.dialog.alert({
1069
+ title: preview.title,
1070
+ message: `Too many wrong passphrases. Try again in ${outcome.retryAfterSec}s (the lockout is audited).`
1071
+ });
1072
+ return;
1073
+ }
828
1074
  });
829
1075
  const trust = guarded(async () => {
830
1076
  const preview = await call("previewTrust");