lobstah 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/main.js +189 -107
  2. package/dist/runner.js +13 -8
  3. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -30,6 +30,10 @@ var init_types = __esm({
30
30
  import * as os from "node:os";
31
31
  import * as path from "node:path";
32
32
  import * as fs from "node:fs";
33
+ import { randomUUID } from "node:crypto";
34
+ function uniqueTempPath(file3) {
35
+ return `${file3}.tmp-${process.pid}-${randomUUID()}`;
36
+ }
33
37
  function readDirIfPresent(dir) {
34
38
  try {
35
39
  return fs.readdirSync(dir);
@@ -352,7 +356,7 @@ function activityFromEvent(ev, root) {
352
356
  }
353
357
  }
354
358
  function atomicWrite(file3, content) {
355
- const tmp = `${file3}.tmp-${process.pid}`;
359
+ const tmp = uniqueTempPath(file3);
356
360
  fs2.writeFileSync(tmp, content);
357
361
  fs2.renameSync(tmp, file3);
358
362
  }
@@ -605,7 +609,7 @@ var init_status = __esm({
605
609
  import * as fs4 from "node:fs";
606
610
  import * as path3 from "node:path";
607
611
  function atomicWrite2(file3, content) {
608
- const tmp = `${file3}.tmp-${process.pid}-${Date.now()}`;
612
+ const tmp = uniqueTempPath(file3);
609
613
  fs4.writeFileSync(tmp, content);
610
614
  fs4.renameSync(tmp, file3);
611
615
  }
@@ -748,7 +752,7 @@ function readEvidence(id, lane) {
748
752
  }
749
753
  function mergeEvidence(id, lane, patch) {
750
754
  const file3 = evidencePath(id, lane);
751
- const tmp = `${file3}.tmp-${process.pid}`;
755
+ const tmp = uniqueTempPath(file3);
752
756
  fs5.writeFileSync(tmp, JSON.stringify({ ...readEvidence(id, lane), ...patch }, null, 2));
753
757
  fs5.renameSync(tmp, file3);
754
758
  }
@@ -1937,7 +1941,7 @@ function setPrTitle(key, title) {
1937
1941
  function writePr(pr) {
1938
1942
  fs8.mkdirSync(prsDir(), { recursive: true });
1939
1943
  const file3 = prRecordFile(pr.key);
1940
- const tmp = `${file3}.tmp-${process.pid}`;
1944
+ const tmp = uniqueTempPath(file3);
1941
1945
  fs8.writeFileSync(tmp, `${JSON.stringify(pr, null, 2)}
1942
1946
  `);
1943
1947
  fs8.renameSync(tmp, file3);
@@ -1987,7 +1991,7 @@ function read() {
1987
1991
  }
1988
1992
  function write(s) {
1989
1993
  fs9.mkdirSync(lobstahHome(), { recursive: true });
1990
- const tmp = `${file()}.${process.pid}.tmp`;
1994
+ const tmp = uniqueTempPath(file());
1991
1995
  fs9.writeFileSync(tmp, JSON.stringify(s));
1992
1996
  fs9.renameSync(tmp, file());
1993
1997
  }
@@ -2103,7 +2107,7 @@ var init_github_budget = __esm({
2103
2107
  });
2104
2108
 
2105
2109
  // packages/core/dist/watch.js
2106
- import * as fs10 from "node:fs";
2110
+ import fs10 from "node:fs";
2107
2111
  import * as path8 from "node:path";
2108
2112
  import { spawnSync } from "node:child_process";
2109
2113
  function watchesDir() {
@@ -2118,12 +2122,67 @@ function watchPath(key) {
2118
2122
  function eventsPath2(key) {
2119
2123
  return path8.join(watchesDir(), `${slug(key)}.events`);
2120
2124
  }
2121
- function writeWatch(w) {
2125
+ function withWatchLock(key, action) {
2122
2126
  fs10.mkdirSync(watchesDir(), { recursive: true });
2127
+ const lock = `${watchPath(key)}.lock`;
2128
+ const deadline = Date.now() + 1e4;
2129
+ const transient = (err) => ["EPERM", "EBUSY", "EACCES"].includes(err.code ?? "");
2130
+ const pause = () => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);
2131
+ for (; ; ) {
2132
+ try {
2133
+ fs10.mkdirSync(lock);
2134
+ break;
2135
+ } catch (err) {
2136
+ const exists = err.code === "EEXIST";
2137
+ if (!exists && !transient(err))
2138
+ throw err;
2139
+ if (exists) {
2140
+ try {
2141
+ if (Date.now() - fs10.statSync(lock).mtimeMs > 12e4)
2142
+ fs10.rmdirSync(lock);
2143
+ } catch {
2144
+ }
2145
+ }
2146
+ if (Date.now() >= deadline)
2147
+ throw exists ? new Error(`Watch locked: ${key}`) : err;
2148
+ pause();
2149
+ }
2150
+ }
2151
+ try {
2152
+ return action();
2153
+ } finally {
2154
+ for (; ; ) {
2155
+ try {
2156
+ fs10.rmdirSync(lock);
2157
+ break;
2158
+ } catch (err) {
2159
+ if (!transient(err) || Date.now() >= deadline)
2160
+ throw err;
2161
+ pause();
2162
+ }
2163
+ }
2164
+ }
2165
+ }
2166
+ function writeWatchUnlocked(w) {
2123
2167
  const file3 = watchPath(w.key);
2124
- const tmp = `${file3}.tmp`;
2125
- fs10.writeFileSync(tmp, JSON.stringify(w, null, 2));
2126
- fs10.renameSync(tmp, file3);
2168
+ const tmp = uniqueTempPath(file3);
2169
+ try {
2170
+ fs10.writeFileSync(tmp, JSON.stringify(w, null, 2));
2171
+ fs10.renameSync(tmp, file3);
2172
+ } finally {
2173
+ fs10.rmSync(tmp, { force: true });
2174
+ }
2175
+ }
2176
+ function currentWatch(w) {
2177
+ return readWatch(w.key)?.createdAt === w.createdAt;
2178
+ }
2179
+ function writeWatch(w, create = false) {
2180
+ return withWatchLock(w.key, () => {
2181
+ if (!create && !currentWatch(w))
2182
+ return false;
2183
+ writeWatchUnlocked(w);
2184
+ return true;
2185
+ });
2127
2186
  }
2128
2187
  function readWatch(key) {
2129
2188
  try {
@@ -2172,7 +2231,7 @@ function addWatch(key, check, opts = {}) {
2172
2231
  heldBy: existing?.heldBy,
2173
2232
  checkRounds: existing?.checkRounds
2174
2233
  };
2175
- writeWatch(w);
2234
+ writeWatch(w, true);
2176
2235
  return w;
2177
2236
  }
2178
2237
  function holdWatch(key, now2 = /* @__PURE__ */ new Date(), opts = {}) {
@@ -2206,10 +2265,12 @@ function releaseHeldWatches(key) {
2206
2265
  return out;
2207
2266
  }
2208
2267
  function removeWatch(key) {
2209
- const existed = fs10.existsSync(watchPath(key));
2210
- fs10.rmSync(watchPath(key), { force: true });
2211
- fs10.rmSync(eventsPath2(key), { force: true });
2212
- return existed;
2268
+ return withWatchLock(key, () => {
2269
+ const existed = fs10.existsSync(watchPath(key));
2270
+ fs10.rmSync(watchPath(key), { force: true });
2271
+ fs10.rmSync(eventsPath2(key), { force: true });
2272
+ return existed;
2273
+ });
2213
2274
  }
2214
2275
  function readWatchEvents(key) {
2215
2276
  try {
@@ -2249,7 +2310,8 @@ function runWatchCheck(w, now2 = /* @__PURE__ */ new Date()) {
2249
2310
  if (isPrPresetWatch(w) && prBatchInFlight(w.key))
2250
2311
  return { watch: w, fresh: [] };
2251
2312
  w.lastCheckedAt = now2.toISOString();
2252
- writeWatch(w);
2313
+ if (!writeWatch(w))
2314
+ return { watch: w, fresh: [] };
2253
2315
  const cmd = w.check.replaceAll("{cursor}", w.cursor);
2254
2316
  const res = spawnSync(cmd, {
2255
2317
  shell: true,
@@ -2258,38 +2320,42 @@ function runWatchCheck(w, now2 = /* @__PURE__ */ new Date()) {
2258
2320
  maxBuffer: 8 * 1024 * 1024,
2259
2321
  env: { ...process.env, ...isPrPresetWatch(w) ? { LOBSTAH_PR_BATCH: "1" } : {} }
2260
2322
  });
2261
- if (res.status !== 0 || res.error) {
2262
- const toonError = /^error:.*$/m.exec(res.stdout ?? "")?.[0];
2263
- const reason = res.error?.message || firstMeaningfulLine(toonError, res.stderr, res.stdout) || "no output";
2264
- recordWatchFailure(w, reason, res.status ?? void 0, now2);
2265
- writeWatch(w);
2266
- return { watch: w, fresh: [] };
2267
- }
2268
- let parsed;
2269
- try {
2270
- parsed = JSON.parse(res.stdout);
2271
- } catch {
2272
- recordWatchFailure(w, `unparseable check output: ${res.stdout.slice(0, 200).trim()}`, void 0, now2);
2273
- writeWatch(w);
2274
- return { watch: w, fresh: [] };
2275
- }
2276
- if (typeof parsed.error === "string" && parsed.error)
2277
- recordWatchFailure(w, parsed.error, void 0, now2);
2278
- else
2279
- recordWatchSuccess(w);
2280
- const events = Array.isArray(parsed.events) ? parsed.events.map((e) => ({
2281
- seq: e.seq ?? w.cursor,
2282
- summary: e.summary !== void 0 ? String(e.summary) : void 0,
2283
- ...e,
2284
- at: now2.toISOString()
2285
- })) : [];
2286
- const fresh = appendWatchEvents(w.key, events);
2287
- if (parsed.cursor !== void 0)
2288
- w.cursor = String(parsed.cursor);
2289
- if (parsed.done === true)
2290
- w.done = true;
2291
- writeWatch(w);
2292
- return { watch: w, fresh };
2323
+ return withWatchLock(w.key, () => {
2324
+ if (!currentWatch(w))
2325
+ return { watch: w, fresh: [] };
2326
+ if (res.status !== 0 || res.error) {
2327
+ const toonError = /^error:.*$/m.exec(res.stdout ?? "")?.[0];
2328
+ const reason = res.error?.message || firstMeaningfulLine(toonError, res.stderr, res.stdout) || "no output";
2329
+ recordWatchFailure(w, reason, res.status ?? void 0, now2);
2330
+ writeWatchUnlocked(w);
2331
+ return { watch: w, fresh: [] };
2332
+ }
2333
+ let parsed;
2334
+ try {
2335
+ parsed = JSON.parse(res.stdout);
2336
+ } catch {
2337
+ recordWatchFailure(w, `unparseable check output: ${res.stdout.slice(0, 200).trim()}`, void 0, now2);
2338
+ writeWatchUnlocked(w);
2339
+ return { watch: w, fresh: [] };
2340
+ }
2341
+ if (typeof parsed.error === "string" && parsed.error)
2342
+ recordWatchFailure(w, parsed.error, void 0, now2);
2343
+ else
2344
+ recordWatchSuccess(w);
2345
+ const events = Array.isArray(parsed.events) ? parsed.events.map((e) => ({
2346
+ seq: e.seq ?? w.cursor,
2347
+ summary: e.summary !== void 0 ? String(e.summary) : void 0,
2348
+ ...e,
2349
+ at: now2.toISOString()
2350
+ })) : [];
2351
+ const fresh = appendWatchEvents(w.key, events);
2352
+ if (parsed.cursor !== void 0)
2353
+ w.cursor = String(parsed.cursor);
2354
+ if (parsed.done === true)
2355
+ w.done = true;
2356
+ writeWatchUnlocked(w);
2357
+ return { watch: w, fresh };
2358
+ });
2293
2359
  }
2294
2360
  function recordWatchFailure(w, reason, exit, now2 = /* @__PURE__ */ new Date()) {
2295
2361
  const cls = classifyGhError(reason);
@@ -2450,7 +2516,7 @@ function cachedPrView(ref) {
2450
2516
  const cached = cycle2.snapshots[ref.key];
2451
2517
  if (cached?.error)
2452
2518
  throw new Error(cached.error);
2453
- return cached?.view;
2519
+ return cached ? { ...cached.view, fetchedAt: new Date(cached.at).toISOString() } : void 0;
2454
2520
  }
2455
2521
  function prBatchQuery(refs) {
2456
2522
  const links = [];
@@ -2548,6 +2614,7 @@ function preparePrWatchBatch(defaultEverySecs, now2 = Date.now(), opts = {}) {
2548
2614
  continue;
2549
2615
  const { query, links } = prBatchQuery(refs);
2550
2616
  const res = (opts.run ?? runBatch)(query, refs[0]);
2617
+ const fetchedAt = Date.now();
2551
2618
  const { headers, body } = splitGitHubResponse(res.stdout);
2552
2619
  let answer = {};
2553
2620
  try {
@@ -2566,7 +2633,7 @@ function preparePrWatchBatch(defaultEverySecs, now2 = Date.now(), opts = {}) {
2566
2633
  recordGitHubRateLimit(now2, Number.isFinite(retry) && retry > 0 ? now2 + retry * 1e3 : void 0);
2567
2634
  }
2568
2635
  const cycle2 = {
2569
- at: now2,
2636
+ at: fetchedAt,
2570
2637
  nextAt: now2 + githubPollIntervalSecs(defaultEverySecs, now2, groups.size) * 1e3,
2571
2638
  snapshots: {},
2572
2639
  links: {}
@@ -2583,23 +2650,28 @@ function preparePrWatchBatch(defaultEverySecs, now2 = Date.now(), opts = {}) {
2583
2650
  cycle2.snapshots[ref.key] = {
2584
2651
  fingerprint: "",
2585
2652
  view: before?.snapshots[ref.key]?.view ?? {},
2586
- at: now2,
2653
+ at: fetchedAt,
2587
2654
  error: answer.errors?.find((e) => e.path?.includes(`pr${ref.number}`))?.message ?? `could not resolve to a PullRequest (${ref.key})`
2588
2655
  };
2589
2656
  continue;
2590
2657
  }
2591
2658
  const fingerprint = createHash("sha256").update(JSON.stringify(raw)).digest("hex");
2592
2659
  const previous = before?.snapshots[ref.key];
2593
- if (previous && !dueRefs.has(ref.key)) {
2594
- cycle2.snapshots[ref.key] = previous;
2660
+ const incomplete = raw.reviews?.pageInfo?.hasPreviousPage || raw.reviewThreads?.pageInfo?.hasNextPage || raw.commits?.nodes?.[0]?.commit.statusCheckRollup?.contexts?.pageInfo?.hasNextPage || answer.errors?.some((e) => e.path?.includes(`pr${ref.number}`));
2661
+ if (incomplete && previous && !dueRefs.has(ref.key) && (fingerprint !== previous.fingerprint || previous.error)) {
2662
+ cycle2.snapshots[ref.key] = {
2663
+ fingerprint,
2664
+ view: toView(raw),
2665
+ at: fetchedAt,
2666
+ error: previous.error ?? `Incomplete PR batch for ${ref.key}; details deferred until the watch is due`
2667
+ };
2595
2668
  continue;
2596
2669
  }
2597
- const incomplete = raw.reviews?.pageInfo?.hasPreviousPage || raw.reviewThreads?.pageInfo?.hasNextPage || raw.commits?.nodes?.[0]?.commit.statusCheckRollup?.contexts?.pageInfo?.hasNextPage || answer.errors?.some((e) => e.path?.includes(`pr${ref.number}`));
2598
2670
  try {
2599
2671
  const view = fingerprint === previous?.fingerprint && !previous.error ? previous.view : incomplete ? (opts.detail ?? ghPrViewDirect)(ref) : toView(raw);
2600
- cycle2.snapshots[ref.key] = { fingerprint, view, at: now2 };
2672
+ cycle2.snapshots[ref.key] = { fingerprint, view, at: fetchedAt };
2601
2673
  } catch (e) {
2602
- cycle2.snapshots[ref.key] = { fingerprint, view: previous?.view ?? toView(raw), at: now2, error: e.message };
2674
+ cycle2.snapshots[ref.key] = { fingerprint, view: previous?.view ?? toView(raw), at: fetchedAt, error: e.message };
2603
2675
  if (classifyGhError(e.message).kind === "rate-limit") {
2604
2676
  recordGitHubRateLimit(now2);
2605
2677
  break;
@@ -2609,7 +2681,7 @@ function preparePrWatchBatch(defaultEverySecs, now2 = Date.now(), opts = {}) {
2609
2681
  for (const link of links)
2610
2682
  cycle2.links[link.key] = repository[link.alias]?.nodes ?? [];
2611
2683
  }
2612
- const tmp = `${file3}.${process.pid}.tmp`;
2684
+ const tmp = uniqueTempPath(file3);
2613
2685
  fs11.writeFileSync(tmp, JSON.stringify(cycle2));
2614
2686
  fs11.renameSync(tmp, file3);
2615
2687
  if (limited)
@@ -2626,7 +2698,7 @@ function cachedPrStackLink(ref, branch, direction) {
2626
2698
  if (!c || c.error)
2627
2699
  return void 0;
2628
2700
  const rows = c.links[`${repoOf(ref)}:${direction}:${branch}`];
2629
- return rows?.map((r) => ({ ...toView(r), number: r.number, url: r.url }));
2701
+ return rows?.map((r) => ({ ...toView(r), fetchedAt: new Date(c.at).toISOString(), number: r.number, url: r.url }));
2630
2702
  }
2631
2703
  var cycleFile, readCycle, repoOf, isPrPresetWatch, prBatchInFlight, fields, runBatch;
2632
2704
  var init_pr_poll = __esm({
@@ -2788,7 +2860,7 @@ function prEvidence(ref, view, observedAt) {
2788
2860
  failingChecks: checks.filter((c) => c.outcome === "failed").map((c) => ({ name: c.name, ...c.detailsUrl ? { detailsUrl: c.detailsUrl } : {} }))
2789
2861
  } : {},
2790
2862
  review: prReview(view),
2791
- observedAt,
2863
+ observedAt: view.fetchedAt ?? observedAt,
2792
2864
  ...view.updatedAt ? { updatedAt: view.updatedAt } : {},
2793
2865
  ...view.mergedAt ? { mergedAt: view.mergedAt } : {},
2794
2866
  ...view.closedAt ? { closedAt: view.closedAt } : {}
@@ -2894,6 +2966,7 @@ function ghPrViewDirect(ref) {
2894
2966
  if (threads !== void 0)
2895
2967
  view.unresolvedThreads = threads;
2896
2968
  }
2969
+ view.fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
2897
2970
  return view;
2898
2971
  }
2899
2972
  function ghPrTitle(ref) {
@@ -3133,7 +3206,7 @@ function syncStackReadiness(cfg = loadConfig(), now2 = Date.now()) {
3133
3206
  };
3134
3207
  const notice = wake || !current ? postNotice(fields2) : { ...current, ...fields2 };
3135
3208
  if (current && !wake) {
3136
- const file4 = path10.join(noticesDir(), `${notice.seq}.json`), tmp2 = `${file4}.tmp-${process.pid}`;
3209
+ const file4 = path10.join(noticesDir(), `${notice.seq}.json`), tmp2 = uniqueTempPath(file4);
3137
3210
  fs12.writeFileSync(tmp2, JSON.stringify(notice));
3138
3211
  fs12.renameSync(tmp2, file4);
3139
3212
  }
@@ -3159,7 +3232,7 @@ function syncStackReadiness(cfg = loadConfig(), now2 = Date.now()) {
3159
3232
  old.at = new Date(now2).toISOString();
3160
3233
  }
3161
3234
  }
3162
- const file3 = stateFile(), tmp = `${file3}.tmp-${process.pid}`;
3235
+ const file3 = stateFile(), tmp = uniqueTempPath(file3);
3163
3236
  fs12.writeFileSync(tmp, JSON.stringify(state));
3164
3237
  fs12.renameSync(tmp, file3);
3165
3238
  });
@@ -3216,7 +3289,7 @@ function postNotice(n) {
3216
3289
  ...n.stateHash ? { stateHash: n.stateHash } : {}
3217
3290
  };
3218
3291
  const file3 = path11.join(dir, `${seq}.json`);
3219
- const tmp = `${file3}.tmp`;
3292
+ const tmp = uniqueTempPath(file3);
3220
3293
  fs13.writeFileSync(tmp, JSON.stringify(notice, null, 2));
3221
3294
  fs13.renameSync(tmp, file3);
3222
3295
  return notice;
@@ -3781,7 +3854,7 @@ function writeKeptWorktrees(list2) {
3781
3854
  fs16.rmSync(file3, { force: true });
3782
3855
  return;
3783
3856
  }
3784
- const tmp = `${file3}.tmp-${process.pid}`;
3857
+ const tmp = uniqueTempPath(file3);
3785
3858
  fs16.writeFileSync(tmp, JSON.stringify(list2, null, 2));
3786
3859
  fs16.renameSync(tmp, file3);
3787
3860
  }
@@ -3940,7 +4013,7 @@ function rosterPath(trapId) {
3940
4013
  function writeEntry(entry) {
3941
4014
  fs18.mkdirSync(rosterDir(), { recursive: true });
3942
4015
  const file3 = rosterPath(entry.trapId);
3943
- const tmp = `${file3}.tmp-${process.pid}`;
4016
+ const tmp = uniqueTempPath(file3);
3944
4017
  fs18.writeFileSync(tmp, `${JSON.stringify(entry, null, 2)}
3945
4018
  `);
3946
4019
  fs18.renameSync(tmp, file3);
@@ -4146,7 +4219,7 @@ function trapStartCommands(repoPath, ticket, harness) {
4146
4219
  function writeReservation(r) {
4147
4220
  fs19.mkdirSync(soakingDir(), { recursive: true });
4148
4221
  const file3 = startPath(r.trapId);
4149
- const tmp = `${file3}.tmp-${process.pid}`;
4222
+ const tmp = uniqueTempPath(file3);
4150
4223
  fs19.writeFileSync(tmp, JSON.stringify(r, null, 2));
4151
4224
  fs19.renameSync(tmp, file3);
4152
4225
  }
@@ -4327,7 +4400,7 @@ function readHold() {
4327
4400
  }
4328
4401
  }
4329
4402
  function writeHold(hold) {
4330
- const tmp = `${holdPath()}.tmp`;
4403
+ const tmp = uniqueTempPath(holdPath());
4331
4404
  fs20.writeFileSync(tmp, JSON.stringify(hold, null, 2));
4332
4405
  fs20.renameSync(tmp, holdPath());
4333
4406
  }
@@ -4368,7 +4441,7 @@ var init_disk = __esm({
4368
4441
  // packages/core/dist/requests.js
4369
4442
  import * as fs21 from "node:fs";
4370
4443
  import * as path19 from "node:path";
4371
- import { randomUUID } from "node:crypto";
4444
+ import { randomUUID as randomUUID2 } from "node:crypto";
4372
4445
  function requestsDir() {
4373
4446
  return path19.join(lobstahHome(), "requests");
4374
4447
  }
@@ -4381,7 +4454,7 @@ function requestFilesDir(id) {
4381
4454
  function write2(r) {
4382
4455
  fs21.mkdirSync(requestsDir(), { recursive: true });
4383
4456
  const file3 = requestPath(r.id);
4384
- const tmp = `${file3}.tmp-${process.pid}`;
4457
+ const tmp = uniqueTempPath(file3);
4385
4458
  fs21.writeFileSync(tmp, JSON.stringify(r, null, 2));
4386
4459
  fs21.renameSync(tmp, file3);
4387
4460
  }
@@ -4410,7 +4483,7 @@ function wakeText(r) {
4410
4483
  return `${r.kind} from the ${r.from} (request ${r.id})`;
4411
4484
  }
4412
4485
  function writeRequest(kind, payload, from = "glass", opts = {}) {
4413
- const r = { id: opts.id ?? randomUUID(), kind, at: (/* @__PURE__ */ new Date()).toISOString(), from, payload };
4486
+ const r = { id: opts.id ?? randomUUID2(), kind, at: (/* @__PURE__ */ new Date()).toISOString(), from, payload };
4414
4487
  write2(r);
4415
4488
  postNotice({
4416
4489
  kind,
@@ -4458,7 +4531,7 @@ var init_requests = __esm({
4458
4531
  REQUEST_KINDS = ["decision-answer", "trap-request"];
4459
4532
  TRAP_HARNESSES = ["claude", "codex"];
4460
4533
  ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
4461
- newRequestId = () => randomUUID();
4534
+ newRequestId = () => randomUUID2();
4462
4535
  }
4463
4536
  });
4464
4537
 
@@ -4582,7 +4655,7 @@ function readJson(file3) {
4582
4655
  }
4583
4656
  function writeJson(file3, value) {
4584
4657
  fs23.mkdirSync(path21.dirname(file3), { recursive: true });
4585
- const tmp = `${file3}.tmp-${process.pid}-${Date.now()}`;
4658
+ const tmp = uniqueTempPath(file3);
4586
4659
  fs23.writeFileSync(tmp, JSON.stringify(value, null, 2));
4587
4660
  fs23.renameSync(tmp, file3);
4588
4661
  }
@@ -4766,7 +4839,7 @@ function helmPath(grounds) {
4766
4839
  }
4767
4840
  function atomicWrite3(file3, content) {
4768
4841
  fs24.mkdirSync(path22.dirname(file3), { recursive: true });
4769
- const tmp = `${file3}.tmp-${process.pid}`;
4842
+ const tmp = uniqueTempPath(file3);
4770
4843
  fs24.writeFileSync(tmp, content);
4771
4844
  fs24.renameSync(tmp, file3);
4772
4845
  }
@@ -5013,7 +5086,7 @@ function observeSessionWorker(input, harness) {
5013
5086
  const text = JSON.stringify(next);
5014
5087
  if (!fs25.existsSync(p) || fs25.readFileSync(p, "utf8") !== text) {
5015
5088
  fs25.mkdirSync(path23.dirname(p), { recursive: true });
5016
- const tmp = `${p}.tmp-${process.pid}`;
5089
+ const tmp = uniqueTempPath(p);
5017
5090
  fs25.writeFileSync(tmp, text);
5018
5091
  fs25.renameSync(tmp, p);
5019
5092
  }
@@ -5040,7 +5113,7 @@ function regPath(trapId) {
5040
5113
  return path24.join(soakingDir(), `${trapId}.json`);
5041
5114
  }
5042
5115
  function atomicWrite4(file3, content) {
5043
- const tmp = `${file3}.tmp-${process.pid}`;
5116
+ const tmp = uniqueTempPath(file3);
5044
5117
  fs26.writeFileSync(tmp, content);
5045
5118
  fs26.renameSync(tmp, file3);
5046
5119
  }
@@ -5807,7 +5880,7 @@ function parseStore(text) {
5807
5880
  function writeStore(store) {
5808
5881
  const file3 = statsPath();
5809
5882
  fs27.mkdirSync(path25.dirname(file3), { recursive: true });
5810
- const tmp = `${file3}.tmp-${process.pid}`;
5883
+ const tmp = uniqueTempPath(file3);
5811
5884
  fs27.writeFileSync(tmp, JSON.stringify(store));
5812
5885
  fs27.renameSync(tmp, file3);
5813
5886
  }
@@ -6078,7 +6151,7 @@ ${markdown}`).digest("hex").slice(0, 16),
6078
6151
  };
6079
6152
  const write4 = (name, content) => {
6080
6153
  const file3 = path26.join(dir, name);
6081
- const tmp = `${file3}.tmp-${process.pid}`;
6154
+ const tmp = uniqueTempPath(file3);
6082
6155
  fs28.writeFileSync(tmp, content);
6083
6156
  fs28.renameSync(tmp, file3);
6084
6157
  };
@@ -6200,7 +6273,7 @@ function decisionDir(key) {
6200
6273
  return m ? path27.join(decisionsRoot(), m[1]) : void 0;
6201
6274
  }
6202
6275
  function writeAtomic(file3, content) {
6203
- const tmp = `${file3}.tmp-${process.pid}`;
6276
+ const tmp = uniqueTempPath(file3);
6204
6277
  fs29.writeFileSync(tmp, content);
6205
6278
  fs29.renameSync(tmp, file3);
6206
6279
  }
@@ -6609,7 +6682,7 @@ function sendMessage(id, lane, text, from, attachments = []) {
6609
6682
  const existing = fs30.readdirSync(dir).filter((f) => f.endsWith(".msg")).length;
6610
6683
  const handled = fs30.readdirSync(path28.join(dir, "handled")).filter((f) => f.endsWith(".msg")).length;
6611
6684
  const name = `${String(existing + handled + 1).padStart(3, "0")}.msg`;
6612
- const tmp = path28.join(dir, `.tmp-${process.pid}-${Date.now()}`);
6685
+ const tmp = uniqueTempPath(path28.join(dir, name));
6613
6686
  if (from !== void 0 || attachments.length > 0) {
6614
6687
  const meta = { from: from ?? "unknown", at: (/* @__PURE__ */ new Date()).toISOString(), ...attachments.length ? { attachments } : {} };
6615
6688
  const metaTmp = `${tmp}.meta`;
@@ -6779,7 +6852,7 @@ function currentRelease(key, stateHash) {
6779
6852
  function writeRelease(r) {
6780
6853
  fs31.mkdirSync(releasesDir(), { recursive: true });
6781
6854
  const file3 = releaseFile(r.key);
6782
- const tmp = `${file3}.tmp-${process.pid}`;
6855
+ const tmp = uniqueTempPath(file3);
6783
6856
  fs31.writeFileSync(tmp, `${JSON.stringify(r, null, 2)}
6784
6857
  `);
6785
6858
  fs31.renameSync(tmp, file3);
@@ -7099,7 +7172,7 @@ function sentPath(id) {
7099
7172
  function write3(e) {
7100
7173
  fs35.mkdirSync(sentDir(), { recursive: true });
7101
7174
  const file3 = sentPath(e.dispatchId);
7102
- const tmp = `${file3}.tmp-${process.pid}`;
7175
+ const tmp = uniqueTempPath(file3);
7103
7176
  fs35.writeFileSync(tmp, `${JSON.stringify(e, null, 2)}
7104
7177
  `);
7105
7178
  fs35.renameSync(tmp, file3);
@@ -7825,7 +7898,7 @@ function readTelemetryState() {
7825
7898
  function writeTelemetryState(state) {
7826
7899
  const file3 = telemetryStatePath();
7827
7900
  fs38.mkdirSync(path34.dirname(file3), { recursive: true });
7828
- const tmp = `${file3}.tmp-${process.pid}`;
7901
+ const tmp = uniqueTempPath(file3);
7829
7902
  fs38.writeFileSync(tmp, `${JSON.stringify(state, null, 2)}
7830
7903
  `);
7831
7904
  fs38.renameSync(tmp, file3);
@@ -8070,7 +8143,7 @@ ${line}
8070
8143
  if (readBack !== share)
8071
8144
  throw new Error(`could not set [telemetry] share in ${file3} \u2014 set \`share = ${share}\` under [telemetry] by hand`);
8072
8145
  fs38.mkdirSync(path34.dirname(file3), { recursive: true });
8073
- const tmp = `${file3}.tmp-${process.pid}`;
8146
+ const tmp = uniqueTempPath(file3);
8074
8147
  fs38.writeFileSync(tmp, next);
8075
8148
  fs38.renameSync(tmp, file3);
8076
8149
  }
@@ -10360,7 +10433,7 @@ async function main(activeDir, lane, seams = {}) {
10360
10433
  wallState.lastHead ??= head();
10361
10434
  const maxWallMs = Math.max(resolved.limits.wallClockSecs ?? 0, cfg.limits.maxWallClockSecs ?? (resolved.limits.wallClockSecs ?? 0) * 4) * 1e3;
10362
10435
  const persistWall = (elapsedMs, windowMs) => {
10363
- const tmp = `${wallFile}.tmp-${process.pid}`;
10436
+ const tmp = uniqueTempPath(wallFile);
10364
10437
  fs89.writeFileSync(tmp, JSON.stringify({ ...wallState, elapsedMs, windowMs }));
10365
10438
  fs89.renameSync(tmp, wallFile);
10366
10439
  };
@@ -10716,7 +10789,7 @@ init_dist3();
10716
10789
  import * as fs91 from "node:fs";
10717
10790
  import * as os13 from "node:os";
10718
10791
  import * as path76 from "node:path";
10719
- import { randomUUID as randomUUID8 } from "node:crypto";
10792
+ import { randomUUID as randomUUID9 } from "node:crypto";
10720
10793
  import { spawnSync as spawnSync17 } from "node:child_process";
10721
10794
  import { fileURLToPath as fileURLToPath6 } from "node:url";
10722
10795
 
@@ -11124,7 +11197,7 @@ function writeHeartbeat(cfg) {
11124
11197
  pid: process.pid,
11125
11198
  heartbeat: (/* @__PURE__ */ new Date()).toISOString()
11126
11199
  };
11127
- const tmp = `${executorPath()}.tmp`;
11200
+ const tmp = uniqueTempPath(executorPath());
11128
11201
  fs42.writeFileSync(tmp, JSON.stringify(payload, null, 2));
11129
11202
  fs42.renameSync(tmp, executorPath());
11130
11203
  }
@@ -11587,7 +11660,7 @@ var PickupState = class {
11587
11660
  this.data.rebases ??= {};
11588
11661
  }
11589
11662
  save() {
11590
- const tmp = `${this.file}.tmp-${process.pid}`;
11663
+ const tmp = uniqueTempPath(this.file);
11591
11664
  fs44.writeFileSync(tmp, JSON.stringify(this.data, null, 2));
11592
11665
  fs44.renameSync(tmp, this.file);
11593
11666
  }
@@ -12088,7 +12161,7 @@ When the change is complete, commit it, push the branch, and open a PR whose des
12088
12161
 
12089
12162
  // apps/pick/dist/loops/dispatch.js
12090
12163
  init_dist2();
12091
- import { randomUUID as randomUUID3 } from "node:crypto";
12164
+ import { randomUUID as randomUUID4 } from "node:crypto";
12092
12165
 
12093
12166
  // apps/pick/dist/loops/report.js
12094
12167
  init_dist2();
@@ -12296,7 +12369,7 @@ async function dispatchLoop(source, state, log = () => {
12296
12369
  log(`${item.key}: claim lost \u2014 another machine has it`);
12297
12370
  continue;
12298
12371
  }
12299
- const id = randomUUID3();
12372
+ const id = randomUUID4();
12300
12373
  const pool = pickupPool(pools, item.repoKey);
12301
12374
  enqueue({
12302
12375
  id,
@@ -12364,7 +12437,7 @@ async function reconcileLoop(source, state, log = () => {
12364
12437
 
12365
12438
  // apps/pick/dist/loops/merge.js
12366
12439
  init_dist2();
12367
- import { randomUUID as randomUUID4 } from "node:crypto";
12440
+ import { randomUUID as randomUUID5 } from "node:crypto";
12368
12441
  import * as fs50 from "node:fs";
12369
12442
  import * as path45 from "node:path";
12370
12443
 
@@ -12385,7 +12458,7 @@ function readMergeView() {
12385
12458
  function writeMergeView(view) {
12386
12459
  const file3 = viewPath();
12387
12460
  fs49.mkdirSync(path44.dirname(file3), { recursive: true });
12388
- const tmp = `${file3}.tmp-${process.pid}`;
12461
+ const tmp = uniqueTempPath(file3);
12389
12462
  fs49.writeFileSync(tmp, JSON.stringify(view, null, 2));
12390
12463
  fs49.renameSync(tmp, file3);
12391
12464
  }
@@ -12558,7 +12631,7 @@ async function mergeLoop(ms, policy, state, log = () => {
12558
12631
  observe(pr, "behind-updated");
12559
12632
  break;
12560
12633
  case "dirty": {
12561
- const uuid = randomUUID4();
12634
+ const uuid = randomUUID5();
12562
12635
  enqueue({
12563
12636
  id: uuid,
12564
12637
  repo: ms.repoKey(),
@@ -12586,7 +12659,7 @@ init_dist2();
12586
12659
  init_dist2();
12587
12660
  import * as fs51 from "node:fs";
12588
12661
  import * as path46 from "node:path";
12589
- import { randomUUID as randomUUID5 } from "node:crypto";
12662
+ import { randomUUID as randomUUID6 } from "node:crypto";
12590
12663
  var DEFAULT_BRIEF = `You are resuming earlier work. The watched source {key} produced new events:
12591
12664
 
12592
12665
  {events}
@@ -12635,7 +12708,7 @@ function spawnContinuation(w, pending, log, fixedBrief, targetOverride) {
12635
12708
  removeWatch(w.key);
12636
12709
  return void 0;
12637
12710
  }
12638
- const id = randomUUID5();
12711
+ const id = randomUUID6();
12639
12712
  const filled = (fixedBrief ?? w.brief ?? DEFAULT_BRIEF).replaceAll("{key}", w.key).replaceAll("{summaries}", pending.map((e) => `- ${e.summary ?? `event ${String(e.seq)}`}`).join("\n")).replaceAll("{events}", JSON.stringify(pending, null, 2));
12640
12713
  const brief = w.key.startsWith("pr:") ? withBriefHooks(filled, loadConfig().repos[descriptor.repo], "ciFix") : filled;
12641
12714
  const claim = readSessionClaim(target, targetLane);
@@ -13001,7 +13074,7 @@ function listAcks() {
13001
13074
  function writeAck(a) {
13002
13075
  fs53.mkdirSync(acksDir(), { recursive: true });
13003
13076
  const file3 = ackFile(a.key);
13004
- const tmp = `${file3}.tmp-${process.pid}`;
13077
+ const tmp = uniqueTempPath(file3);
13005
13078
  fs53.writeFileSync(tmp, `${JSON.stringify(a, null, 2)}
13006
13079
  `);
13007
13080
  fs53.renameSync(tmp, file3);
@@ -13531,7 +13604,7 @@ function dispatchPrList(urls, prs) {
13531
13604
  init_dist2();
13532
13605
  import * as fs57 from "node:fs";
13533
13606
  import * as path51 from "node:path";
13534
- import { randomUUID as randomUUID6 } from "node:crypto";
13607
+ import { randomUUID as randomUUID7 } from "node:crypto";
13535
13608
  import { spawnSync as spawnSync6 } from "node:child_process";
13536
13609
 
13537
13610
  // apps/cli/src/repair-holds.ts
@@ -13669,7 +13742,7 @@ function repairHold(pr, records, workers) {
13669
13742
  var beatFile = () => path51.join(lobstahHome(), "repairer.json");
13670
13743
  function stampRepairerBeat(now2 = Date.now(), processName = "daemon") {
13671
13744
  fs57.mkdirSync(lobstahHome(), { recursive: true });
13672
- const tmp = `${beatFile()}.tmp-${process.pid}`;
13745
+ const tmp = uniqueTempPath(beatFile());
13673
13746
  fs57.writeFileSync(tmp, JSON.stringify({ process: processName, pid: process.pid, at: new Date(now2).toISOString() }));
13674
13747
  fs57.renameSync(tmp, beatFile());
13675
13748
  }
@@ -14021,7 +14094,7 @@ function deliverPrRepairs(log, cap = 3, opts = {}) {
14021
14094
  const until2 = new Date(cooldownUntil).toISOString();
14022
14095
  return wait({ heldBy: "cooldown", reason: `cooldown until ${until2}` }, until2);
14023
14096
  }
14024
- const id = randomUUID6();
14097
+ const id = randomUUID7();
14025
14098
  writePr({
14026
14099
  ...pr,
14027
14100
  repairCooldown: { dispatchId: id },
@@ -15185,7 +15258,7 @@ function recordHookRun(event, harness, now2 = Date.now()) {
15185
15258
  if (now2 - (Date.parse(runs[key] ?? "") || 0) < RECORD_EVERY_MS) return;
15186
15259
  runs[key] = new Date(now2).toISOString();
15187
15260
  const file3 = hookRunsPath();
15188
- const tmp = `${file3}.tmp-${process.pid}`;
15261
+ const tmp = uniqueTempPath(file3);
15189
15262
  fs60.writeFileSync(tmp, JSON.stringify(runs, null, 2));
15190
15263
  fs60.renameSync(tmp, file3);
15191
15264
  } catch {
@@ -15280,7 +15353,7 @@ async function pruneGlassState() {
15280
15353
  function writeGlassState(state) {
15281
15354
  const file3 = stateFile2();
15282
15355
  fs62.mkdirSync(path55.dirname(file3), { recursive: true });
15283
- const tmp = `${file3}.tmp-${process.pid}`;
15356
+ const tmp = uniqueTempPath(file3);
15284
15357
  try {
15285
15358
  fs62.writeFileSync(tmp, JSON.stringify(state, null, 2) + "\n");
15286
15359
  fs62.renameSync(tmp, file3);
@@ -16829,7 +16902,7 @@ function armWatcher(sessionId, kind, trapId) {
16829
16902
  };
16830
16903
  const beat = () => {
16831
16904
  if (!ownsFile()) return;
16832
- const tmp = `${file3}.tmp-${process.pid}`;
16905
+ const tmp = uniqueTempPath(file3);
16833
16906
  try {
16834
16907
  fs70.writeFileSync(tmp, `${JSON.stringify(own())}
16835
16908
  `);
@@ -17329,7 +17402,7 @@ import { randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from
17329
17402
  import { fileURLToPath as fileURLToPath3 } from "node:url";
17330
17403
 
17331
17404
  // apps/cli/src/glass-page.generated.ts
17332
- var GLASS_PAGE = '<!doctype html>\n<html>\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width,initial-scale=1" />\n <title>spyglass</title>\n <link rel="icon" type="image/png" href="/icon.png" />\n <style>:root{--bg: #0e1116;--card: #161b22;--line: #2b3240;--line-hover: #3a455a;--row-hover: #1c2330;--inset: #10151c;--seg-on: #26436b;--scrim: rgba(4, 7, 11, 0.72);--fg: #dbe2ea;--dim: #8b96a5;--ok: #4fc17c;--warn: #e2b93d;--bad: #e26d5c;--link: #6cb2e2;--on-fill: #fff;--pr-merged: #8957e5;--pr-merged-fg: #ab7df8;--pr-open: #238636;--pr-draft: #6e7681;--pr-closed: #da3633;--lobstah: #eb6644;--heat-0: var(--inset);--heat-1: color-mix(in srgb, var(--lobstah) 30%, var(--card));--heat-2: color-mix(in srgb, var(--lobstah) 55%, var(--card));--heat-3: color-mix(in srgb, var(--lobstah) 78%, var(--card));--heat-4: var(--lobstah);--heat-cell: 11px;--heat-gap: 3px;--font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;--font-size: 13px;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--page-pad-block: 14px;--radius: 6px;--card-radius: 8px;--card-pad: 12px 14px;--card-min: 300px;--deck-card-min: 240px;--badge-radius: 5px;--badge-pad: 1px 7px;--badge-font: 11px;--modal-radius: 10px;--modal-width: 780px;--layer-modal: 10;--layer-decision-modal: 15;--layer-alert: calc(var(--layer-modal) - 1);--unread-bg: color-mix(in srgb, var(--bad) 16%, var(--card))}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:var(--font-size)/1.45 var(--font-mono);padding-block:var(--page-pad-block);padding-inline:var(--space-4);display:flex;flex-direction:column;min-height:100vh}h1{font-size:15px;margin:0 0 10px}h1 .dim{color:var(--dim);font-weight:normal}h2{font-size:12px;color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;margin:20px 0 6px}.chips,.controls{display:flex;gap:var(--space-2);flex-wrap:wrap;align-items:center}.controls{margin:0 0 14px}.chips{margin-bottom:8px}.chip{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:3px 9px}.controls select,.newtrap select,.controls input[type=search]{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);color:var(--fg);font:inherit;padding:4px 8px}.controls input[type=search]{flex:1 1 140px;min-width:120px;max-width:340px}#chain-control{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}#f-chain{margin:0;width:14px;height:14px;accent-color:var(--link)}.tabs{display:flex;gap:var(--space-1);border-bottom:1px solid var(--line);margin:8px 0 10px}.tabs a{color:var(--dim);padding:6px 11px;border-bottom:2px solid transparent}.tabs a.on{color:var(--fg);border-color:var(--link)}.tabpage{display:none}.tabpage.on{display:block;flex:1 0 auto}.headerline{display:flex;align-items:center;gap:var(--space-2)}.headerline h1{flex:1}#settings-slot{min-width:34px;text-align:right;color:var(--dim)}#settings-slot #gearbtn{margin-left:0}.deckgrid{display:flex;flex-direction:column;gap:var(--space-3)}.deckgrid h2{margin:5px 0}.deckgrid section{width:100%;min-width:0}.deckline{padding:2px 0;border-top:1px solid var(--line);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.deckline{display:flex;gap:0.35em}a.deckline>b{min-width:0;overflow:hidden;text-overflow:ellipsis}a.deckline>.dim{flex-shrink:0}.deckline.acked,.card.acked,.rowhead.acked,.badge.acked{opacity:0.55}.deckmore{color:var(--dim);font-size:11px;display:inline-block;margin-top:4px}.deckline.click{cursor:pointer}.deckline.click:hover{background:var(--row-hover)}.deckgrid h2 a{color:inherit}.deckgrid h2 a:hover{color:var(--fg)}.deckgrid .cards{grid-template-columns:repeat(auto-fill,minmax(min(var(--deck-card-min),100%),1fr));gap:10px}.deckstack{margin-bottom:9px}.deckstack>.dim{font-size:11px;margin:3px 0 5px}.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.seg button{background:var(--card);border:none;color:var(--dim);font:inherit;padding:4px 11px;cursor:pointer}.seg button.on{background:var(--seg-on);color:var(--fg)}.wrap{overflow-x:auto}table{border-collapse:collapse;width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}th,td{text-align:left;padding:4px 9px;border-top:1px solid var(--line);vertical-align:top;white-space:nowrap}td.grow{white-space:normal;word-break:break-word;min-width:140px}th{color:var(--dim);font-weight:normal;border-top:none;font-size:11px}tr.rowhead{cursor:pointer}tr.rowhead:hover{background:var(--row-hover)}.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--card-min),100%),1fr));gap:var(--space-3)}.card{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad);cursor:pointer;min-width:0;overflow:hidden;overflow-wrap:anywhere}.card:hover{border-color:var(--line-hover)}.worker-harness{cursor:help}.worker-harness:focus-visible{outline:2px solid var(--ok);outline-offset:3px}.worker-tooltip{position:fixed;z-index:20;max-width:264px;padding:6px 9px;background:var(--card);color:var(--fg);border:1px solid var(--line-hover);border-radius:var(--badge-radius);box-shadow:0 3px 12px var(--scrim);font-size:12px;white-space:normal;pointer-events:none}.worker-details dl{display:grid;grid-template-columns:max-content 1fr;gap:4px 14px;font-size:12px}.worker-details dt{color:var(--dim)}.worker-details dd{margin:0;overflow-wrap:anywhere}.card .top{display:flex;justify-content:space-between;gap:var(--space-3);align-items:center;min-height:22px}.card .top>b,.card .top>.prname{flex:1 1000000 auto;min-width:min(10ch,100%);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card .top .badge{flex:0 0 auto}.card .top .badge.long{flex:0 1 auto;min-width:min(12ch,100%);max-width:min(26ch,100%);overflow:hidden;text-overflow:ellipsis}.card .meta{color:var(--dim);font-size:12px;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.card .note{margin-top:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.activity{margin-top:4px;font-size:12px;color:var(--fg);opacity:0.85}.waiting{margin-top:4px;font-size:12px;color:var(--dim)}.activity.stale{color:var(--dim);opacity:1}.card .foot{margin-top:8px;display:flex;gap:10px;flex-wrap:wrap;align-items:center;color:var(--dim);font-size:12px}.card .foot>*{min-width:0}.card .foot .footact{margin-left:auto}.catchn{white-space:nowrap}.btn{background:var(--card);border:1px solid var(--line);border-radius:5px;color:var(--dim);font:inherit;font-size:11px;padding:1px 8px;cursor:pointer;white-space:nowrap}.btn:hover{color:var(--fg);border-color:var(--line-hover)}.badge{border-radius:var(--badge-radius);padding:var(--badge-pad);font-size:var(--badge-font);line-height:1.5;border:1px solid var(--line);white-space:nowrap;display:inline-block}.badge.pr-merged{background:var(--pr-merged);border-color:var(--pr-merged-fg);color:var(--on-fill)}.badge.pr-open{background:var(--pr-open);border-color:var(--pr-open);color:var(--on-fill)}.badge.pr-draft{background:var(--pr-draft);border-color:var(--pr-draft);color:var(--on-fill)}.badge.pr-closed{background:var(--pr-closed);border-color:var(--pr-closed);color:var(--on-fill)}.badge.pr-conflicts{background:var(--pr-closed);border-color:var(--pr-closed);color:var(--on-fill)}.badge.pr-behind{background:var(--pr-draft);border-color:var(--pr-draft);color:var(--on-fill)}.badge.unreported{font-weight:normal;font-size:10px;padding:0 5px;vertical-align:1px}.v-done{color:var(--ok)}.v-working,.v-queued{color:var(--fg)}.v-needs-decision,.v-blocked{color:var(--bad);font-weight:bold}.v-failed{color:var(--bad)}.v-paused,.v-unknown{color:var(--dim)}.dim{color:var(--dim)}.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}.detail{display:none}.detail.open{display:table-row}.detail td{background:var(--inset);white-space:pre-wrap;word-break:break-word;font-size:12px;color:var(--dim)}.detail b{color:var(--fg)}.empty{color:var(--dim);padding:6px 2px}.older{padding:8px 2px}#stale{display:none;color:var(--bad)}a{color:var(--link);text-decoration:none}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:middle}.dot.ok{background:var(--ok)}.dot.warn{background:var(--warn)}.dot.bad{background:var(--bad)}.dot.dim{background:var(--dim)}#overlay{position:fixed;inset:0;background:var(--scrim);display:none;z-index:var(--layer-modal);padding:28px 16px;overflow:auto}#overlay.open{display:block}.modal{max-width:var(--modal-width);margin:0 auto;background:var(--card);border:1px solid var(--line);border-radius:var(--modal-radius);padding:16px 18px;position:relative}.modal .x{position:absolute;top:8px;right:12px;cursor:pointer;color:var(--dim);font-size:18px;line-height:1}.modal .x:hover{color:var(--fg)}.modal h3{margin:0 24px 2px 0;font-size:14px}.modal .sub{color:var(--dim);font-size:12px;margin-bottom:10px}.modal .sec{color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;font-size:11px;margin:14px 0 4px}.modal pre{white-space:pre-wrap;word-break:break-word;margin:0;font:inherit;color:var(--fg)}.msg{border-left:3px solid var(--line);padding:3px 10px;margin:8px 0;white-space:pre-wrap;word-break:break-word}.msg.from-helm{border-color:var(--link)}.msg .hdr{color:var(--dim);font-size:11px}.catch{border:1px solid var(--line);border-radius:var(--radius);padding:6px 10px;margin:8px 0}.catch.click{cursor:pointer}.catch .hdr{display:flex;gap:10px;flex-wrap:wrap;align-items:baseline}.loglines{color:var(--dim);font-size:12px;white-space:pre-wrap;word-break:break-word;margin-top:4px}.cmd{display:flex;gap:var(--space-2);align-items:center;margin:5px 0;flex-wrap:wrap}.cmd code{background:var(--inset);border:1px solid var(--line);border-radius:5px;padding:3px 8px;word-break:break-all;cursor:pointer}.cmd.inline{display:inline-flex;margin:0}.cmd code:hover{border-color:var(--line-hover)}.cmd code.copied{border-color:var(--ok)}.cmd button{background:var(--card);border:1px solid var(--line);border-radius:5px;color:var(--dim);font:inherit;font-size:11px;padding:2px 8px;cursor:pointer}.cmd button:hover{color:var(--fg)}.chip.click{cursor:pointer}.chip.click:hover{border-color:var(--line-hover)}footer{margin-top:26px;padding-top:10px;border-top:1px solid var(--line);color:var(--dim);font-size:12px;display:flex;gap:var(--space-2);flex-wrap:wrap}.lob{position:fixed;bottom:6px;left:0;z-index:5;cursor:pointer;font-size:34px;line-height:1;user-select:none;animation:crawl 18s linear infinite}a.lob{color:inherit}.lob .bub .badge{display:inline-block;margin:0 0 3px}.pet-art{display:block;position:relative;width:72px;height:56px}.pet-art .sprite{width:72px;height:56px;background-position:0 0;background-repeat:no-repeat;background-size:400% 100%;image-rendering:pixelated;animation:step 0.5s steps(4) infinite}.lob .bub{display:none;position:absolute;bottom:58px;right:-8px;z-index:2;background:var(--card);border:1px solid var(--line);border-radius:9px;padding:6px 9px 5px;font-size:11px;line-height:1.35;color:var(--fg);width:max-content;max-width:150px;box-shadow:0 2px 8px rgba(0,0,0,0.4)}.lob:hover .bub{display:block}.lob .bub span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:normal;word-break:break-word}.pet-art .star{position:absolute;left:56px;top:-9px;height:14px;image-rendering:pixelated;z-index:3}.lob:hover{animation-play-state:paused}@keyframes crawl{0%{transform:translateX(-90px)}100%{transform:translateX(100vw)}}@keyframes step{to{background-position-x:-288px}}#gearbtn{background:none;border:1px solid var(--line);border-radius:var(--radius);color:var(--dim);font:inherit;font-size:13px;padding:1px 7px;margin-left:8px;cursor:pointer;vertical-align:1px}#gearbtn:hover,#gearbtn.on{color:var(--fg);border-color:var(--line-hover)}.settings .row{display:flex;justify-content:space-between;align-items:center;gap:14px;margin:12px 0}.settings .lbl{color:var(--fg);font-size:12px}.settings .hint{display:block;color:var(--dim);font-size:11px;margin-top:2px}.dlist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.drow{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2);background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:8px 12px}.drow.unread{background:var(--unread-bg);border-color:var(--bad)}.drow.answered{opacity:0.7}.drow.focus{animation:dflash 1.6s ease-out 1}.drow .dopen{flex:1 1 280px;display:flex;align-items:baseline;gap:var(--space-2);min-width:0;background:none;border:none;padding:0;color:var(--fg);font:inherit;text-align:left;cursor:pointer}.drow .dopen:hover .dtitle{text-decoration:underline}.drow .dtitle{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drow .dmeta,.drow .dage{font-size:11px}.drow .dlink,.dmodal .dlink{color:var(--link)}.dstate{font-size:var(--badge-font);border-radius:var(--badge-radius);padding:var(--badge-pad);border:1px solid var(--line);color:var(--dim)}.dstate.unread{border-color:var(--bad);color:var(--bad)}.dstate.answered{color:var(--ok)}.dbadge{display:inline-block;margin-left:6px;min-width:1.6em;text-align:center;border-radius:999px;padding:0 6px;font-size:11px;font-weight:bold;background:var(--bad);color:var(--on-fill)}#doverlay{position:fixed;inset:0;background:var(--scrim);z-index:var(--layer-decision-modal);padding:28px 16px;overflow:auto}.dmodal:focus{outline:none}.dmodal .x{background:none;border:none;font:inherit;font-size:18px;color:var(--dim)}.dnav{display:flex;align-items:center;gap:var(--space-2);margin:0 28px var(--space-3) 0}.dnav .dpos{color:var(--dim);font-size:11px}.dmodal .dtop{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2);margin-bottom:var(--space-2)}.dmodal .dtitle{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px}.dmodal .dmeta{font-size:11px}.ddone{padding:28px 8px;text-align:center;cursor:pointer}.ddone .ok{font-size:15px;margin-bottom:var(--space-2)}.dalert-live{position:fixed;right:var(--space-4);bottom:var(--space-4);z-index:var(--layer-alert)}.dalert{display:flex;align-items:center;gap:4px;background:var(--card);border:1px solid var(--bad);border-radius:var(--card-radius);padding:8px 10px;box-shadow:0 6px 24px var(--scrim)}.dalert .dalert-open{display:flex;align-items:center;gap:var(--space-2);background:none;border:none;color:var(--fg);font:inherit;cursor:pointer}.dalert .dx{background:none;border:none;color:var(--dim);font:inherit;font-size:15px;cursor:pointer}.dcount{display:inline-block;min-width:1.8em;text-align:center;border-radius:999px;padding:1px 7px;font-weight:bold;background:var(--bad);color:var(--on-fill);animation:dglow 1.8s ease-in-out infinite}@keyframes dglow{0%,100%{box-shadow:0 0 0 0 transparent}50%{box-shadow:0 0 10px 3px var(--bad)}}@media(prefers-reduced-motion:reduce){.dcount,.drow.focus{animation:none}}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@keyframes dflash{0%,35%{border-color:var(--link);box-shadow:0 0 0 3px var(--link)}100%{border-color:var(--line);box-shadow:0 0 0 0 transparent}}.dfiles{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:6px 0}.dfiles .dimg img{max-height:160px;max-width:320px;border:1px solid var(--line);border-radius:var(--radius);display:block}.dfiles .dfile{width:100%;font-size:11px}.doptions{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 6px}.btn.dopt{font-size:12px;padding:3px 12px;color:var(--fg)}.btn.dopt.on{background:var(--seg-on);border-color:var(--link)}.danswer{display:block;width:100%;min-height:3.2em;max-height:50vh;margin:6px 0;padding:6px 8px;resize:vertical;overflow-y:auto;field-sizing:content;background:var(--inset);color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);font:inherit}.dkey,.dlegend kbd{display:inline-block;min-width:1.5em;text-align:center;font:inherit;font-size:10px;line-height:1.4;padding:0 4px;border:1px solid var(--line-hover);border-radius:4px;color:var(--dim);background:var(--inset)}.btn.dopt .dkey{margin-right:6px}.btn.dopt.on .dkey{border-color:var(--link);color:var(--fg)}.danswer-wrap{position:relative}.danswer-wrap .dkey-text{position:absolute;top:6px;right:8px;pointer-events:none}.dlegend{margin-top:var(--space-3);padding-top:var(--space-2);border-top:1px solid var(--line);font-size:11px;line-height:1.9}.danswer:focus{outline:none;border-color:var(--line-hover)}.dfoot{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.dfoot .dattach input{display:none}.dfoot .dchip{font-size:11px;border:1px solid var(--line);border-radius:var(--badge-radius);padding:0 0 0 6px}.dfoot .dx{background:none;border:none;color:var(--dim);cursor:pointer;font:inherit}.dfoot .derr{font-size:11px}.btn.dsend{margin-left:auto;color:var(--fg);padding:2px 14px}.btn:disabled{cursor:default;opacity:0.6}.danswered{margin-top:6px}.thumb,.dimg,.mdimg{background:none;border:none;padding:0;cursor:zoom-in;font:inherit}.thumb{display:block;margin:4px 0}.thumb img{max-height:120px;max-width:240px;border:1px solid var(--line);border-radius:var(--radius);display:block}.lightbox{position:fixed;inset:0;z-index:20;background:rgba(0,0,0,0.85);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2)}.lightbox .lbimg{max-width:90vw;max-height:90vh;object-fit:contain;border-radius:var(--radius);box-shadow:0 8px 40px rgba(0,0,0,0.6)}.lightbox .lbclose{position:absolute;top:12px;right:16px;background:none;border:none;color:var(--fg);font-size:28px;line-height:1;cursor:pointer}.lightbox .lboriginal{color:var(--link);font-size:12px}.mdpage{background:var(--inset);border:1px solid var(--line);border-radius:6px;padding:8px 14px;margin:6px 0;line-height:1.5;overflow-wrap:anywhere}.mdpage h1,.mdpage h2,.mdpage h3,.mdpage h4{margin:12px 0 6px;line-height:1.25}.mdpage h1{font-size:18px}.mdpage h2{font-size:15px}.mdpage h3,.mdpage h4{font-size:13px}.mdpage p,.mdpage ul,.mdpage ol,.mdpage blockquote{margin:6px 0}.mdpage ul,.mdpage ol{padding-left:22px}.mdpage a{color:var(--link)}.mdpage code{background:var(--card);border-radius:3px;padding:0 3px}.mdpage pre.mdcode{background:var(--card);border:1px solid var(--line);border-radius:4px;padding:8px;max-width:100%;overflow-x:auto;white-space:pre;overflow-wrap:normal}.mdpage pre.mdcode code{padding:0;background:none}.mdpage blockquote{border-left:3px solid var(--line);padding-left:10px;color:var(--dim)}.mdpage img{max-width:100%;height:auto;border-radius:4px;display:block;margin:6px 0}.mdpage hr{border:0;border-top:1px solid var(--line)}.mdpage .mdtable{max-width:100%;overflow-x:auto}.mdpage table{border-collapse:collapse;margin:6px 0}.mdpage th,.mdpage td{border:1px solid var(--line);padding:3px 8px;text-align:left;white-space:normal;overflow-wrap:anywhere;min-width:12ch}.tabhead{margin:0 0 8px}.newtrap{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:12px;font-weight:normal;text-transform:none;letter-spacing:normal}.startcmds{margin:6px 0;font-size:11px;cursor:default}.reportview{width:100%;max-width:1100px;margin:0 auto;padding:20px 16px 48px;overflow-wrap:anywhere}.reportview h1{font-size:18px;margin:0 0 4px}.reportview .sub{color:var(--dim);font-size:12px;margin-bottom:10px}.reportview .sec{color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;font-size:11px;margin:14px 0 4px}.reportview .mdpage{padding:12px 20px}@media(max-width:600px){.reportview{padding:12px 0 32px}.reportview .mdpage{padding:8px 12px}}.stats{display:flex;flex-direction:column;gap:var(--space-4);max-width:100%}.stats h2{margin:0 0 var(--space-2)}.stat-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:var(--space-2)}.stat-tile{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.stat-tile .n{font-size:22px;font-weight:bold;color:var(--fg)}.stats-empty{display:flex;align-items:center;gap:var(--space-4);background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--space-4) var(--space-4) var(--space-3)}.stats-empty .pet-art{flex:none;margin-top:6px}.heat{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad);min-width:0}.heat-scroll{overflow-x:auto;padding:2px 0 4px}.heatmap{border-collapse:separate;border-spacing:var(--heat-gap);width:auto;margin:0;background:none;border:0;border-radius:0;overflow:visible}.heatmap td{padding:0;border:0;vertical-align:middle;font-size:10px;line-height:1;color:var(--dim)}.heatmap .month{position:relative;height:14px}.heatmap .month span{position:absolute;left:0;bottom:3px;white-space:nowrap}.heatmap .wd{position:sticky;left:0;z-index:1;background:var(--card);padding-right:var(--space-1);white-space:nowrap}.heatmap .day,.heatmap .pad,.heat-legend .swatch{width:var(--heat-cell);min-width:var(--heat-cell);height:var(--heat-cell);border-radius:2px}.heatmap .day{position:relative;cursor:default;outline:1px solid rgba(255,255,255,0.04);outline-offset:-1px}.heatmap .day:focus-visible{outline:2px solid var(--link);outline-offset:0}.l0{background:var(--heat-0)}.l1{background:var(--heat-1)}.l2{background:var(--heat-2)}.l3{background:var(--heat-3)}.l4{background:var(--heat-4)}.heatmap .day:hover::after,.heatmap .day:focus::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);z-index:4;background:var(--bg);border:1px solid var(--line-hover);border-radius:var(--badge-radius);color:var(--fg);font-size:11px;padding:3px 7px;white-space:nowrap;pointer-events:none}.heatmap .day.below:hover::after,.heatmap .day.below:focus::after{bottom:auto;top:calc(100% + 6px)}.heatmap .day.tl:hover::after,.heatmap .day.tl:focus::after{left:0;transform:none}.heatmap .day.tr:hover::after,.heatmap .day.tr:focus::after{left:auto;right:0;transform:none}.heat-foot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--space-2);font-size:11px;margin-top:var(--space-1)}.heat-legend{display:inline-flex;align-items:center;gap:var(--heat-gap);color:var(--dim);margin-left:auto}.heat-legend .swatch{display:inline-block}.heat-legend .swatch:first-of-type{margin-left:var(--space-1)}.heat-legend .swatch:last-of-type{margin-right:var(--space-1)}.top-traps{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.top-traps ol{list-style:none;margin:0;padding:0;display:grid;gap:6px}.top-traps li{display:grid;grid-template-columns:minmax(0,14em) minmax(40px,32em) auto;justify-content:start;align-items:center;gap:var(--space-3)}.top-traps .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.top-traps .bar{height:6px;background:var(--inset);border-radius:3px;overflow:hidden}.top-traps .bar span{display:block;height:100%;background:var(--lobstah)}.top-traps .n{color:var(--dim);white-space:nowrap}@media(max-width:600px){.tabs{flex-wrap:wrap}.tabs a{white-space:nowrap}}</style>\n </head>\n <body>\n <!-- The page is rendered by Preact (src/components/app.ts): header, tabs, controls, the five tab pages, footer, lobs, modal overlay. -->\n <script>"use strict";(()=>{var Ve,y,Sn,zr,W,bn,Dn,xn,yt,Be,ve,Gn,St,_t,wt,Jr,Fe={},qe=[],Yr=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,ze=Array.isArray;function L(e,t){for(var n in t)e[n]=t[n];return e}function Dt(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Z(e,t,n){var s,r,o,a={};for(o in t)o=="key"?s=t[o]:o=="ref"?r=t[o]:a[o]=t[o];if(arguments.length>2&&(a.children=arguments.length>3?Ve.call(arguments,2):n),typeof e=="function"&&e.defaultProps!=null)for(o in e.defaultProps)a[o]===void 0&&(a[o]=e.defaultProps[o]);return Ue(e,a,s,r,null)}function Ue(e,t,n,s,r){var o={type:e,props:t,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++Sn,__i:-1,__u:0};return r==null&&y.vnode!=null&&y.vnode(o),o}function ee(e){return e.children}function We(e,t){this.props=e,this.context=t}function V(e,t){if(t==null)return e.__?V(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type=="function"?V(e):null}function Qr(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,s=[],r=[],o=L({},t);o.__v=t.__v+1,y.vnode&&y.vnode(o),xt(e.__P,o,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,s,n??V(t),!!(32&t.__u),r),o.__v=t.__v,o.__.__k[o.__i]=o,Mn(s,o,r),t.__e=t.__=null,o.__e!=n&&Cn(o)}}function Cn(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),Cn(e)}function yn(e){(!e.__d&&(e.__d=!0)&&W.push(e)&&!Ke.__r++||bn!=y.debounceRendering)&&((bn=y.debounceRendering)||Dn)(Ke)}function Ke(){try{for(var e,t=1;W.length;)W.length>t&&W.sort(xn),e=W.shift(),t=W.length,Qr(e)}finally{W.length=Ke.__r=0}}function Tn(e,t,n,s,r,o,a,l,u,c,d){var h,p,m,f,$,_,x=s&&s.__k||qe,b=t.length;for(u=Xr(n,t,x,u,b),h=0;h<b;h++)(m=n.__k[h])!=null&&(p=m.__i!=-1&&x[m.__i]||Fe,m.__i=h,_=xt(e,m,p,r,o,a,l,u,c,d),f=m.__e,m.ref&&p.ref!=m.ref&&(p.ref&&Gt(p.ref,null,m),d.push(m.ref,m.__c||f,m)),$==null&&f!=null&&($=f),4&m.__u?(u=An(m,u,e),p.__e&&(p.__e=null)):typeof m.type=="function"&&_!==void 0?u=_:f&&(u=f.nextSibling),m.__u&=-7);return n.__e=$,u}function Xr(e,t,n,s,r){var o,a,l,u,c,d=n.length,h=d,p=0;for(e.__k=new Array(r),o=0;o<r;o++)(a=t[o])!=null&&typeof a!="boolean"&&typeof a!="function"?(typeof a=="string"||typeof a=="number"||typeof a=="bigint"||a.constructor==String?a=e.__k[o]=Ue(null,a,null,null,null):ze(a)?a=e.__k[o]=Ue(ee,{children:a},null,null,null):a.constructor===void 0&&a.__b>0?a=e.__k[o]=Ue(a.type,a.props,a.key,a.ref?a.ref:null,a.__v):e.__k[o]=a,u=o+p,a.__=e,a.__b=e.__b+1,l=null,(c=a.__i=Zr(a,n,u,h))!=-1&&(h--,(l=n[c])&&(l.__u|=2)),l==null||l.__v==null?(c==-1&&(r>d?p--:r<d&&p++),typeof a.type!="function"&&(a.__u|=4)):c!=u&&(c==u-1?p--:c==u+1?p++:(c>u?p--:p++,a.__u|=4))):e.__k[o]=null;if(h)for(o=0;o<d;o++)(l=n[o])!=null&&(2&l.__u)==0&&(l.__e==s&&(s=V(l)),In(l,l));return s}function An(e,t,n){var s,r;if(typeof e.type=="function"){for(s=e.__k,r=0;s&&r<s.length;r++)s[r]&&(s[r].__=e,t=An(s[r],t,n));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=V(e)),t=n.insertBefore(e.__e,t||null));do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function Zr(e,t,n,s){var r,o,a,l=e.key,u=e.type,c=t[n],d=c!=null&&(2&c.__u)==0;if(c===null&&l==null||d&&l==c.key&&u==c.type)return n;if(s>(d?1:0)){for(r=n-1,o=n+1;r>=0||o<t.length;)if((c=t[a=r>=0?r--:o++])!=null&&(2&c.__u)==0&&l==c.key&&u==c.type)return a}return-1}function _n(e,t,n){t[0]=="-"?e.setProperty(t,n??""):e[t]=n==null?"":typeof n!="number"||Yr.test(t)?n:n+"px"}function je(e,t,n,s,r){var o,a;e:if(t=="style")if(typeof n=="string")e.style.cssText=n;else{if(typeof s=="string"&&(e.style.cssText=s=""),s)for(t in s)n&&t in n||_n(e.style,t,"");if(n)for(t in n)s&&n[t]==s[t]||_n(e.style,t,n[t])}else if(t[0]=="o"&&t[1]=="n")o=t!=(t=t.replace(Gn,"$1")),a=t.toLowerCase(),t=a in e||t=="onFocusOut"||t=="onFocusIn"?a.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+o]=n,n?s?n[ve]=s[ve]:(n[ve]=St,e.addEventListener(t,o?wt:_t,o)):e.removeEventListener(t,o?wt:_t,o);else{if(r=="http://www.w3.org/2000/svg")t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(t!="width"&&t!="height"&&t!="href"&&t!="list"&&t!="form"&&t!="tabIndex"&&t!="download"&&t!="rowSpan"&&t!="colSpan"&&t!="role"&&t!="popover"&&t in e)try{e[t]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&n==1?"":n))}}function wn(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[Be]==null)t[Be]=St++;else if(t[Be]<n[ve])return;return n(y.event?y.event(t):t)}}}function xt(e,t,n,s,r,o,a,l,u,c){var d,h,p,m,f,$,_,x,b,P,ge,K,$e,kn,He,bt,I=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(u=!!(32&n.__u),o=[l=t.__e=n.__e]),(d=y.__b)&&d(t);e:if(typeof I=="function"){h=a.length;try{if(b=t.props,P=I.prototype&&I.prototype.render,ge=(d=I.contextType)&&s[d.__c],K=d?ge?ge.props.value:d.__:s,n.__c?x=(p=t.__c=n.__c).__=p.__E:(P?t.__c=p=new I(b,K):(t.__c=p=new We(b,K),p.constructor=I,p.render=to),ge&&ge.sub(p),p.state||(p.state={}),p.__n=s,m=p.__d=!0,p.__h=[],p._sb=[]),P&&p.__s==null&&(p.__s=p.state),P&&I.getDerivedStateFromProps!=null&&(p.__s==p.state&&(p.__s=L({},p.__s)),L(p.__s,I.getDerivedStateFromProps(b,p.__s))),f=p.props,$=p.state,p.__v=t,m)P&&I.getDerivedStateFromProps==null&&p.componentWillMount!=null&&p.componentWillMount(),P&&p.componentDidMount!=null&&p.__h.push(p.componentDidMount);else{if(P&&I.getDerivedStateFromProps==null&&b!==f&&p.componentWillReceiveProps!=null&&p.componentWillReceiveProps(b,K),t.__v==n.__v||!p.__e&&p.shouldComponentUpdate!=null&&p.shouldComponentUpdate(b,p.__s,K)===!1){t.__v!=n.__v&&(p.props=b,p.state=p.__s,p.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(X){X&&(X.__=t)}),qe.push.apply(p.__h,p._sb),p._sb=[],p.__h.length&&a.push(p),l=V(n);break e}p.componentWillUpdate!=null&&p.componentWillUpdate(b,p.__s,K),P&&p.componentDidUpdate!=null&&p.__h.push(function(){p.componentDidUpdate(f,$,_)})}if(p.context=K,p.props=b,p.__P=e,p.__e=!1,$e=y.__r,kn=0,P)p.state=p.__s,p.__d=!1,$e&&$e(t),d=p.render(p.props,p.state,p.context),qe.push.apply(p.__h,p._sb),p._sb=[];else do p.__d=!1,$e&&$e(t),d=p.render(p.props,p.state,p.context),p.state=p.__s;while(p.__d&&++kn<25);p.state=p.__s,p.getChildContext!=null&&(s=L(L({},s),p.getChildContext())),P&&!m&&p.getSnapshotBeforeUpdate!=null&&(_=p.getSnapshotBeforeUpdate(f,$)),He=d!=null&&d.type===ee&&d.key==null?Pn(d.props.children):d,l=Tn(e,ze(He)?He:[He],t,n,s,r,o,a,l,u,c),p.base=t.__e,t.__u&=-161,p.__h.length&&a.push(p),x&&(p.__E=p.__=null)}catch(X){if(a.length=h,t.__v=null,u||o!=null){if(X.then){for(t.__u|=u?160:128;l&&l.nodeType==8&&l.nextSibling;)l=l.nextSibling;o!=null&&(o[o.indexOf(l)]=null),t.__e=l}else if(o!=null)for(bt=o.length;bt--;)Dt(o[bt])}else t.__e=n.__e;t.__k==null&&(t.__k=n.__k||[]),X.then||Rn(t),y.__e(X,t,n)}}else o==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):l=t.__e=eo(n.__e,t,n,s,r,o,a,u,c);return(d=y.diffed)&&d(t),128&t.__u?void 0:l}function Rn(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(Rn))}function Mn(e,t,n){for(var s=0;s<n.length;s++)Gt(n[s],n[++s],n[++s]);y.__c&&y.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(o){o.call(r)})}catch(o){y.__e(o,r.__v)}})}function Pn(e){return typeof e!="object"||e==null||e.__b>0?e:ze(e)?e.map(Pn):e.constructor!==void 0?null:L({},e)}function eo(e,t,n,s,r,o,a,l,u){var c,d,h,p,m,f,$,_=n.props||Fe,x=t.props,b=t.type;if(b=="svg"?r="http://www.w3.org/2000/svg":b=="math"?r="http://www.w3.org/1998/Math/MathML":r||(r="http://www.w3.org/1999/xhtml"),o!=null){for(c=0;c<o.length;c++)if((m=o[c])&&"setAttribute"in m==!!b&&(b?m.localName==b:m.nodeType==3)){e=m,o[c]=null;break}}if(e==null){if(b==null)return document.createTextNode(x);e=document.createElementNS(r,b,x.is&&x),l&&(y.__m&&y.__m(t,o),l=!1),o=null}if(b==null)_===x||l&&e.data==x||(e.data=x);else{if(o=b=="textarea"&&x.defaultValue!=null?null:o&&Ve.call(e.childNodes),!l&&o!=null)for(_={},c=0;c<e.attributes.length;c++)_[(m=e.attributes[c]).name]=m.value;for(c in _)m=_[c],c=="dangerouslySetInnerHTML"?h=m:c=="children"||c in x||c=="value"&&"defaultValue"in x||c=="checked"&&"defaultChecked"in x||je(e,c,null,m,r);for(c in x)m=x[c],c=="children"?p=m:c=="dangerouslySetInnerHTML"?d=m:c=="value"?f=m:c=="checked"?$=m:l&&typeof m!="function"||_[c]===m||je(e,c,m,_[c],r);if(d)l||h&&(d.__html==h.__html||d.__html==e.innerHTML)||(e.innerHTML=d.__html),t.__k=[];else if(h&&(e.innerHTML=""),Tn(t.type=="template"?e.content:e,ze(p)?p:[p],t,n,s,b=="foreignObject"?"http://www.w3.org/1999/xhtml":r,o,a,o?o[0]:n.__k&&V(n,0),l,u),o!=null)for(c=o.length;c--;)Dt(o[c]);l&&b!="textarea"||(c="value",b=="progress"&&f==null?e.removeAttribute("value"):f!=null&&(f!==e[c]||b=="progress"&&!f||b=="option"&&f!=_[c])&&je(e,c,f,_[c],r),c="checked",$!=null&&$!=e[c]&&je(e,c,$,_[c],r))}return e}function Gt(e,t,n){try{if(typeof e=="function"){var s=typeof e.__u=="function";s&&e.__u(),s&&t==null||(e.__u=e(t))}else e.current=t}catch(r){y.__e(r,n)}}function In(e,t,n){var s,r;if(y.unmount&&y.unmount(e),(s=e.ref)&&(s.current&&s.current!=e.__e||Gt(s,null,t)),(s=e.__c)!=null){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(o){y.__e(o,t)}s.base=s.__P=s.__n=null}if(s=e.__k)for(r=0;r<s.length;r++)s[r]&&In(s[r],t,n||typeof e.type!="function");n||Dt(e.__e),e.__c=e.__=e.__e=void 0}function to(e,t,n){return this.constructor(e,n)}function Ct(e,t,n){var s,r,o,a;t==document&&(t=document.documentElement),y.__&&y.__(e,t),r=(s=typeof n=="function")?null:n&&n.__k||t.__k,o=[],a=[],xt(t,e=(!s&&n||t).__k=Z(ee,null,[e]),r||Fe,Fe,t.namespaceURI,!s&&n?[n]:r?null:t.firstChild?Ve.call(t.childNodes):null,o,!s&&n?n:r?r.__e:t.firstChild,s,a),Mn(o,e,a),e.props.children=null}Ve=qe.slice,y={__e:function(e,t,n,s){for(var r,o,a;t=t.__;)if((r=t.__c)&&!r.__)try{if((o=r.constructor)&&o.getDerivedStateFromError!=null&&(r.setState(o.getDerivedStateFromError(e)),a=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,s||{}),a=r.__d),a)return r.__E=r}catch(l){e=l}throw e}},Sn=0,zr=function(e){return e!=null&&e.constructor===void 0},We.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=L({},this.state),typeof e=="function"&&(e=e(L({},n),this.props)),e&&L(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),yn(this))},We.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),yn(this))},We.prototype.render=ee,W=[],Dn=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,xn=function(e,t){return e.__v.__b-t.__v.__b},Ke.__r=0,yt=Math.random().toString(8),Be="__d"+yt,ve="__a"+yt,Gn=/(PointerCapture)$|Capture$/i,St=0,_t=wn(!1),wt=wn(!0),Jr=0;var te=e=>e>999?"999+":String(e);function ne(e){return e.harness==="codex"?!!e.desktopThread||e.link?.startsWith("codex://threads/")===!0||e.window?.bundleId==="com.openai.codex":e.harness==="claude"?e.window?.entrypoint==="claude-desktop"||!e.window?.entrypoint&&e.link?.startsWith("claude://claude.ai/")===!0:!1}function Hn(e){let{harness:t,sessionId:n}=e;if(!ne(e)&&n){if(t==="codex")return"codex resume "+n;if(t==="claude")return"claude --resume "+n}}function no(e){return{id:e,lane:"work",bucket:"done",repo:"",title:"",verb:"unknown",sort:0}}var En=new WeakMap;function Tt(e,t){let n=e.dispatches||[],s=En.get(n);return s||En.set(n,s=new Map(n.map(r=>[r.id,r]))),{...t,catches:(t.catches||[]).map(r=>s.get(r)??no(r))}}function E(e){if(!e)return"dim";let t=e.state||"open";return t==="open"&&e.merge?"pr-"+e.merge:t==="open"&&e.tone&&e.tone!=="ok"?e.tone:"pr-"+t}var se=["deck","dispatches","traps","prs","reports","notices","stats"];function jn(e){let t=String(e||"").replace(/^#/,"");return se.includes(t)?t:"deck"}var At=e=>`#decision/${encodeURIComponent(e)}`;function re(e){let t=/^#?decision\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var Rt=(e,t,n)=>`/attachment/dispatch/${encodeURIComponent(e)}/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,Bn=(e,t)=>`/attachment/trap/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,Un=e=>/\\.(png|jpe?g|gif|webp)$/i.test(e),Mt=(e,t)=>`/decision/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function Je(e,t){let n=new Map(t.map(r=>[r.key,r])),s=[];for(let r of e)if(r.kind==="decision"){let o=n.get(r.key);if(!o)continue;s.push({kind:"decision",key:o.key,title:o.title,detail:o.detail,options:o.options,attachments:o.attachments,...o.dispatch?{dispatch:o.dispatch,lane:o.lane??"work"}:{},...o.repo?{repo:o.repo}:{},at:o.askedAt,...o.viewedAt??r.viewedAt?{viewedAt:o.viewedAt??r.viewedAt}:{}})}else r.kind==="question"&&s.push({kind:"question",key:r.key,verb:r.verb,note:r.note||r.verb,dispatch:r.id,lane:r.lane,...r.repo?{repo:r.repo}:{},at:r.at??"",...r.viewedAt?{viewedAt:r.viewedAt}:{}});return s.sort((r,o)=>o.at.localeCompare(r.at)||r.key.localeCompare(o.key))}function Wn(e){let t=(e.text??"").split(`\n`).map(n=>n.trim()).find(Boolean)??"";return[e.option,t&&(t.length>80?t.slice(0,79)+"\\u2026":t),e.files?`${e.files} file${e.files===1?"":"s"}`:""].filter(Boolean).join(" \\xB7 ")}function Fn(e,t){return(e.reports||[]).find(n=>n.key===`report:${t.lane}:${t.id}`)}function ke(e){return e.author==="helm"?"":e.trap?e.trap:e.author==="headless"?e.dispatch?e.dispatch.slice(0,8):"":e.author}var On=(e,t)=>+!!e.acked-+!!t.acked||t.filedAt.localeCompare(e.filedAt),G=e=>`/report/${encodeURIComponent(e)}`;function be(e){let t=/^#?report\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}function qn(e){return typeof e!="string"?!1:e===""?!0:e.length>1024||!e.startsWith("#")||/[\\s\\x00-\\x1f\\x7f]/.test(e)?!1:se.includes(e.slice(1))||re(e)!==null||be(e)!==null}function Kn(e){let t=/^\\/report\\/([^/?#]+)\\/?$/.exec(e);if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var Vn=e=>`/report/${encodeURIComponent(e)}/md`,Pt=(e,t)=>`/report/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`,It={dispatches:[],notices:[],prs:[],stacks:[]};function zn(e,t){if(t.kind==="dispatches"){let r=new Set(e.dispatches.map(o=>o.lane+":"+o.id));return{...e,dispatches:[...e.dispatches,...t.items.filter(o=>!r.has(o.lane+":"+o.id))]}}if(t.kind==="notices"){let r=new Set(e.notices.map(o=>o.seq));return{...e,notices:[...e.notices,...t.items.filter(o=>!r.has(o.seq))]}}let n=new Set(e.prs.map(r=>r.key)),s=new Set(e.stacks.map(r=>r.id));return{...e,prs:[...e.prs,...t.items.filter(r=>!n.has(r.key))],stacks:[...e.stacks,...t.stacks.filter(r=>!s.has(r.id))]}}function Jn(e,t){if(t===It||!t.dispatches.length&&!t.notices.length&&!t.prs.length)return e;let n=new Set(e.dispatches.map(a=>a.lane+":"+a.id)),s=new Set(e.notices.map(a=>a.seq)),r=new Set(e.prs.map(a=>a.key)),o=new Set(e.stacks.map(a=>a.id));return{...e,dispatches:[...e.dispatches,...t.dispatches.filter(a=>!n.has(a.lane+":"+a.id))],notices:[...e.notices,...t.notices.filter(a=>!s.has(a.seq))],prs:[...e.prs,...t.prs.filter(a=>!r.has(a.key))],stacks:[...e.stacks,...t.stacks.filter(a=>!o.has(a.id))]}}function Yn(e,t,n){return Math.max(0,(e.older?.[n]??0)-t[n].length)}function Qn(e,t){return{...e,now:t.now,daemon:e.daemon&&t.daemon!==void 0?{...e.daemon,heartbeat:t.daemon}:e.daemon,helms:e.helms.map(n=>t.helms[n.grounds]!==void 0?{...n,heartbeatAt:t.helms[n.grounds]}:n),traps:e.traps.map(n=>t.traps[n.trapId]?{...n,...t.traps[n.trapId]}:n)}}function Ln(e,t,n){return!!e&&n-Date.parse(e)>t}function Nn(e,t){if(t.lane&&e.lane!==t.lane||t.repo&&e.repo!==t.repo||t.verb&&e.verb!==t.verb)return!1;if(t.q){let n=t.q.toLowerCase();if(!(e.id+" "+(e.note||"")+" "+(e.title||"")+" "+(e.repo||"")+" "+(e.for||"")).toLowerCase().includes(n))return!1}return!0}function oe(e,t,n){if(!t)return null;if(t.type==="helm")return e.helms.find(r=>r.grounds===t.key)||null;if(t.type==="dispatch"){let r=e.dispatches.find(a=>a.lane+":"+a.id===t.key),o=n&&n.key===t.key?n.data:void 0;return r&&o?{...r,...o}:r??o??null}if(t.type==="pr")return(e.prs||[]).find(r=>r.key===t.key)||null;if(t.type==="settings")return{attentionKinds:e.attentionKinds||[],attentionError:e.attentionError};let s=e.traps.find(r=>r.trapId===t.key);return s?Tt(e,s):null}function Xn(e,t,n){let s=t.st,r=String(s.q||"").toLowerCase(),o=(...f)=>!r||f.join(" ").toLowerCase().includes(r),a=f=>({x:f,stale:Ln(f.heartbeatAt,18e5,n)}),l=oe(e,t.modal,t.detail),u=(f,$)=>!!f&&n-Date.parse(f)<=$,c=f=>Math.max(0,...(f.notices||[]).filter($=>$.kind==="trap-stowed"||$.kind==="trap-ghosted").map($=>Date.parse($.at)||0)),d=f=>f.live||!!f.starting||!!f.requested,h=[...e.traps||[]].sort((f,$)=>Number(d($))-Number(d(f))||Number($.live)-Number(f.live)||(f.live?(Date.parse(f.signedOnAt||"")||0)-(Date.parse($.signedOnAt||"")||0):c($)-c(f))||(f.name??f.trapId).localeCompare($.name??$.trapId)),p=h.filter(f=>(d(f)||(f.notices||[]).some($=>($.kind==="trap-stowed"||$.kind==="trap-ghosted")&&u($.at,36e5)))&&o(f.name,f.trapId,f.repo,f.worktree)),m=({ageSecs:f,...$})=>$;return{chips:{daemon:e.daemon,daemonStale:!!e.daemon&&Ln(e.daemon.heartbeat,9e4,n),helms:e.helms.map(a),stats:e.stats},deck:{view:s.view,decisions:Je(e.attention||[],e.decisions||[]).filter(f=>f.kind==="decision"?o(f.kind,f.repo,f.title,f.dispatch,f.detail):o(f.kind,f.repo,f.note,f.dispatch)),prAttention:(e.attention||[]).filter(f=>f.kind&&f.kind.startsWith("pr:")).map(m),landed:(e.landed||[]).filter(f=>u(f.at,864e5)&&o(f.repo,f.note,f.id)).sort((f,$)=>Date.parse($.at)-Date.parse(f.at)).slice(0,8),reports:(e.reports||[]).filter(f=>o(f.title,f.author,f.dispatch,f.repo)).sort(On),inflight:e.dispatches.filter(f=>f.bucket!=="done"&&Nn(f,{...s,lane:"",repo:"",verb:""})),traps:p.map(f=>a(Tt(e,f))),stacks:(e.stacks||[]).filter(f=>f.open&&o(f.repo,f.numbers.join(" "))),prs:(e.prs||[]).filter(f=>f.state==="OPEN"),error:e.attentionError},dispatches:{view:s.view,chain:s.chain,list:e.dispatches.filter(f=>Nn(f,s))},traps:{view:s.view,list:h.filter(f=>(!s.repo||f.repo===s.repo)&&o(f.name,f.trapId,f.repo,f.worktree,f.harness)).map(f=>a(Tt(e,f)))},prs:{view:s.view,stacks:(e.stacks||[]).filter(f=>!s.repo||f.repo===s.repo),prs:(e.prs||[]).filter(f=>(!s.repo||f.repo===s.repo)&&o(f.number,f.title,f.url,f.state,f.baseRefName,f.headRefName)),watches:(e.watches||[]).filter(f=>!String(f.key).startsWith("pr:"))},reports:{view:s.view,list:(e.reports||[]).filter(f=>(!s.repo||f.repo===s.repo)&&o(f.title,f.author,f.dispatch,f.repo)).sort(On)},notices:{list:(e.notices||[]).filter(f=>(!s.repo||!f.repo||f.repo===s.repo)&&(!s.noticeKind||f.kind===s.noticeKind)&&o(f.kind,f.text,f.repo))},foot:{version:e.version,repoUrl:e.repoUrl},modal:{modal:t.modal,item:l&&a(l),prefs:t.modal&&t.modal.type==="settings"?{view:s.view,lobs:s.lobs}:void 0}}}function Zn(e,t){let n=(e.prs||[]).find(l=>l.key===t);if(!n)return null;let s=(e.stacks||[]).find(l=>l.id===n.stackId),r=new Map((e.dispatches||[]).map(l=>[l.id,l])),o=(n.dispatchIds||[]).map(l=>{let u=r.get(l);return u?{id:l,verb:u.verb,modalKey:u.lane+":"+u.id}:{id:l,culled:!0}}),a=n.watch;return{pr:n,stack:s?{numbers:s.numbers,titles:s.numbers.map(l=>(e.prs||[]).find(u=>u.stackId===s.id&&u.number===l)?.title||""),position:n.position+1,size:s.numbers.length,floor:s.floor,nextNumber:s.nextNumber,nextMergeable:!!n.nextMergeable,blockedBy:n.blockedBy}:null,chain:o,watch:a?{key:a.key,owner:a.owner||"",lastCheckedAt:a.lastCheckedAt||null,lastError:a.lastError||null,cursor:a.cursor}:null}}function es(e){return e?{text:e.lastError?"failing":"watching",at:e.lastCheckedAt||null}:{text:"no watch",at:null}}function Ye(e,t){return e.filter(n=>!t(n.key)).sort((n,s)=>n.at.localeCompare(s.at)||n.key.localeCompare(s.key))}function ts(e,t,n){return Ye(e,t).filter(s=>!s.viewedAt&&!n(s.key))}function ns(){let e={view:"table",lane:"",repo:"",verb:"",q:"",lobs:!0,chain:!1,noticeKind:""};try{Object.assign(e,JSON.parse(localStorage.getItem("spyglass")||"{}"))}catch{}return e.view!=="table"&&e.view!=="cards"&&(e.view="table"),e.lobs=e.lobs!==!1,e}function ss(e){try{localStorage.setItem("spyglass",JSON.stringify(e))}catch{}}function rs(){try{return JSON.parse(localStorage.getItem("spyglass-lob-hidden")||"{}")||{}}catch{return{}}}function os(e){try{localStorage.setItem("spyglass-lob-hidden",JSON.stringify(e))}catch{}}var ye,Qe;function ae(e){if(e.snapshot)return(Qe?.snapshot!==e.snapshot||Qe.older!==e.older)&&(Qe={snapshot:e.snapshot,older:e.older,view:Jn(e.snapshot,e.older)}),Qe.view}var as=new Set,g=()=>ye;function Et(e){ye=e}function k(e){ye={...ye,...e};for(let t of as)t(ye)}var Ot=e=>{as.add(e)};function so(e,t){let n=ae(e);return n&&oe(n,t,e.detail)?!0:t.type==="dispatch"&&e.detail?.key===t.key&&!e.detail.error}function Xe(e){let{modal:t,drafts:n,older:s,detail:r,decisionModal:o}=g(),a=Je(e.attention||[],e.decisions||[]),l=new Set(a.map(c=>c.key)),u=Object.fromEntries(Object.entries(n).filter(([c])=>l.has(c)));k({snapshot:e,stale:!1,modal:t&&so({snapshot:e,older:s,detail:r},t)?t:null,...Object.keys(u).length!==Object.keys(n).length?{drafts:u}:{},...o?.key&&!l.has(o.key)&&!n[o.key]?.sent?{decisionModal:is(a,u,o.key)}:{}})}function is(e,t,n){let s=Ye(e,o=>!!t[o]?.sent||o===n);if(!s.length)return null;let r=e.find(o=>o.key===n)?.at??"";return{key:(s.find(o=>o.at>r||o.at===r&&o.key>(n??""))??s[0]).key}}function Ze(){let e=ae(g());return e?Je(e.attention||[],e.decisions||[]):[]}function _e(){let{drafts:e}=g();return Ye(Ze(),t=>!!e[t]?.sent)}function et(){let{drafts:e,viewedHere:t}=g();return ts(Ze(),n=>!!e[n]?.sent,n=>!!t[n])}function ie(e){let t=e??et()[0]?.key??_e()[0]?.key;t&&k({decisionModal:{key:t}})}function we(e){let t=g().decisionModal;if(!t?.key)return;let n=_e(),s=n.findIndex(o=>o.key===t.key),r=n[s+e];s>=0&&r&&k({decisionModal:{key:r.key}})}var le=()=>k({decisionModal:null}),Se=9;function ro(){let e=g().decisionModal?.key;return e?_e().find(t=>t.key===e):void 0}function ls(e){let t=ro();if(!t||e<1||e>Se)return!1;let n=g().drafts[t.key];if(n?.sending||n?.sent)return!1;let s=t.kind==="decision"?t.options:[];return e<=s.length?(A(t.key,{option:s[e-1],error:void 0}),document.querySelectorAll(".dmodal .dopt")[e-1]?.focus(),!0):e===s.length+1?(document.querySelector(".dmodal textarea.danswer")?.focus(),!0):!1}async function ds(e){let t=g();if(t.viewedHere[e]||(k({viewedHere:{...t.viewedHere,[e]:!0}}),Ze().find(s=>s.key===e)?.viewedAt))return;let n=t.snapshot?.focusToken;if(n)try{await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":n},body:JSON.stringify({kind:"decision-viewed",payload:{key:e}})})}catch{}}function cs(){k({alertDismissed:et().map(e=>e.key)})}function ps(e){let{snapshot:t}=g();k({stale:!1,...t?{snapshot:Qn(t,e)}:{}})}async function Nt(){let{modal:e}=g();if(e?.type!=="dispatch")return;let t=e.key,n=t.slice(t.indexOf(":")+1),s;try{let o=await fetch(`/data/dispatch/${encodeURIComponent(n)}`,{cache:"no-store"});s=o.ok?{data:await o.json()}:{error:o.status===404?"this dispatch is gone":`the detail answered ${o.status}`}}catch{s={error:"the detail could not be read"}}let r=g();r.modal?.type!=="dispatch"||r.modal.key!==t||s.error&&r.detail?.key===t&&r.detail.data||k({detail:{key:t,...s}})}var Lt=!1;async function De(){if(!Lt){Lt=!0;try{let e=await fetch("/data/stats",{cache:"no-store"});if(!e.ok)throw new Error(`/data/stats answered ${e.status}`);k({stats:await e.json(),statsError:null})}catch{k({statsError:"stats could not be read"})}finally{Lt=!1}}}var Ht=e=>{g().statsFocus!==e&&k({statsFocus:e})};async function us(e){let{olderLoading:t,older:n}=g();if(!t){k({olderLoading:e,olderError:null});try{let s=await fetch(`/data/older?kind=${e}&offset=${n[e].length}&limit=50`,{cache:"no-store"});if(!s.ok)throw new Error(`/data/older answered ${s.status}`);let r=await s.json();k({older:zn(g().older,r),olderLoading:null})}catch{k({olderLoading:null,olderError:{kind:e,text:"older records could not be read"}})}}}var fs=()=>({text:"",files:[]});function A(e,t){let n=g().drafts;k({drafts:{...n,[e]:{...n[e]??fs(),...t}}})}function ms(e,t){let n=g().drafts[e]?.option;A(e,{option:n===t?void 0:t,error:void 0})}var oo=e=>new Promise((t,n)=>{let s=new FileReader;s.onload=()=>t(String(s.result).replace(/^data:[^,]*,/,"")),s.onerror=()=>n(s.error),s.readAsDataURL(e)});async function jt(e,t){let n=g().snapshot?.answerLimits,s=[...t??[]],r=g().drafts[e]?.files??[],o=[],a=[];for(let l of s){let u=(/\\.[^.]+$/.exec(l.name)?.[0]??"").toLowerCase();if(n&&!n.extensions.includes(u))o.push(`${l.name}: type not accepted`);else if(n&&l.size>n.maxBytes)o.push(`${l.name}: larger than ${n.maxBytes} bytes`);else if(n&&r.length+a.length>=n.maxFiles)o.push(`${l.name}: at most ${n.maxFiles} files`);else try{a.push({name:l.name,bytes:l.size,data:await oo(l)})}catch{o.push(`${l.name}: could not be read`)}}A(e,{files:[...g().drafts[e]?.files??[],...a],error:o.length?o.join("; "):void 0})}var ao={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};async function hs(e,t){let n=[...t.clipboardData?.items??[]],s=new Date().toISOString().replace(/[:.]/g,"-").replace(/-\\d{3}Z$/,"Z"),r=n.filter(o=>o.kind==="file"&&o.type.startsWith("image/")).map(o=>o.getAsFile()).filter(o=>o!==null).map((o,a,l)=>{let u=`pasted-${s}${l.length>1?`-${a+1}`:""}${ao[o.type]??".png"}`;return new File([o],u,{type:o.type})});r.length&&await jt(e,r)}function gs(e,t){let n=(g().drafts[e]?.files??[]).filter((s,r)=>r!==t);A(e,{files:n})}async function tt(e){let t=g().snapshot?.focusToken,n=g().drafts[e]??fs();if(!(n.sending||n.sent)){if(!n.option&&!n.text.trim()&&n.files.length===0){A(e,{error:"Choose an option, write an answer, or attach a file."});return}if(!t){A(e,{error:"This page has no answer token; reload it."});return}A(e,{sending:!0,error:void 0});try{let s=await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":t},body:JSON.stringify({kind:"decision-answer",payload:{key:e,...n.option?{option:n.option}:{},...n.text.trim()?{text:n.text}:{},files:n.files.map(a=>({name:a.name,data:a.data}))}})}),r=await s.json();if(!s.ok||!r.ok){A(e,{sending:!1,error:r.reason??`The answer was refused (${s.status}).`});return}A(e,{sending:!1,sent:Wn({option:n.option,text:n.text,files:n.files.length})}),g().decisionModal?.key===e&&k({decisionModal:is(Ze(),g().drafts,e)??{key:null}})}catch{A(e,{sending:!1,error:"The answer could not be sent."})}}}var $s=()=>k({stale:!0}),vs=(e,t)=>k({lightbox:{src:e,name:t}}),de=()=>k({lightbox:null});function O(e,t){let n=g(),s={type:e,key:t};if(e==="dispatch"){k({modal:s,detail:n.detail?.key===t?n.detail:{key:t}}),Nt();return}let r=ae(n);k({modal:!r||oe(r,s)?s:null,detail:null})}function ce(){k({modal:null,detail:null})}async function ks(e){let t=g().snapshot?.focusToken;if(t)try{let s=await(await fetch(`/api/focus/${encodeURIComponent(e)}`,{method:"POST",headers:{"x-lobstah-focus-token":t}})).json();k({focusResults:{...g().focusResults,[e]:s.message??s.reason??"Window focus failed."}})}catch{k({focusResults:{...g().focusResults,[e]:"Window focus failed."}})}}async function bs(e,t){let n=g().snapshot?.focusToken;if(!n)return"The glass has no page token yet.";try{let r=await(await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":n},body:JSON.stringify({kind:"trap-request",payload:{repo:e,harness:t}})})).json();if(!r.ok)return r.reason??"The request was refused."}catch{return"The request could not be sent."}try{Xe(await(await fetch("/data")).json())}catch{}}function N(e){let t={...g().prefs,...e};ss(t),k({prefs:t})}function ys(e){e!=="table"&&e!=="cards"||N({view:e})}var _s=e=>N({lobs:e==="on"});function ws(e,t){let n={...g().lobHidden,[e]:t};os(n),setTimeout(()=>k({lobHidden:n}),0)}async function Ss(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}var xs=function(e,t,n,s){var r;t[0]=0;for(var o=1;o<t.length;o++){var a=t[o++],l=t[o]?(t[0]|=a?1:2,n[t[o++]]):t[++o];a===3?s[0]=l:a===4?s[1]=Object.assign(s[1]||{},l):a===5?(s[1]=s[1]||{})[t[++o]]=l:a===6?s[1][t[++o]]+=l+"":a?(r=e.apply(l,xs(e,l,n,["",null])),s.push(r),l[0]?t[0]|=2:(t[o-2]=0,t[o]=r)):s.push(l)}return s},Ds=new Map;function Gs(e){var t=Ds.get(this);return t||(t=new Map,Ds.set(this,t)),(t=xs(this,t.get(e)||(t.set(e,t=(function(n){for(var s,r,o=1,a="",l="",u=[0],c=function(p){o===1&&(p||(a=a.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,"")))?u.push(0,p,a):o===3&&(p||a)?(u.push(3,p,a),o=2):o===2&&a==="..."&&p?u.push(4,p,0):o===2&&a&&!p?u.push(5,0,!0,a):o>=5&&((a||!p&&o===5)&&(u.push(o,0,a,r),o=6),p&&(u.push(o,p,0,r),o=6)),a=""},d=0;d<n.length;d++){d&&(o===1&&c(),c(d));for(var h=0;h<n[d].length;h++)s=n[d][h],o===1?s==="<"?(c(),u=[u],o=3):a+=s:o===4?a==="--"&&s===">"?(o=1,a=""):a=s+a[0]:l?s===l?l="":a+=s:s===\'"\'||s==="\'"?l=s:s===">"?(c(),o=1):o&&(s==="="?(o=5,r=a,a=""):s==="/"&&(o<5||n[d][h+1]===">")?(c(),o===3&&(u=u[0]),o=u,(u=u[0]).push(2,0,o),o=0):s===" "||s===" "||s===`\n`||s==="\\r"?(c(),o=2):a+=s),o===3&&a==="!--"&&(o=4,u=u[0])}return c(),u})(e)),t),arguments,[])).length>1?t:t[0]}var Cs=e=>Array.isArray(e)?e.map(Cs):e===""?null:e,io=(e,t,...n)=>Z(e,t,...n.map(Cs)),i=Gs.bind(io);var xe,w,Bt,Ts,st=0,Ls=[],D=y,As=D.__b,Rs=D.__r,Ms=D.diffed,Ps=D.__c,Is=D.unmount,Es=D.__;function Wt(e,t){D.__h&&D.__h(w,e,st||t),st=0;var n=w.__H||(w.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function z(e){return st=1,lo(Hs,e)}function lo(e,t,n){var s=Wt(xe++,2);if(s.t=e,!s.__c&&(s.__=[n?n(t):Hs(void 0,t),function(l){var u=s.__N?s.__N[0]:s.__[0],c=s.t(u,l);u!==c&&(s.__N=[c,s.__[1]],s.__c.setState({}))}],s.__c=w,!w.__f)){var r=function(l,u,c){if(!s.__c.__H)return!0;var d=!1,h=s.__c.props!==l;if(s.__c.__H.__.some(function(m){if(m.__N){d=!0;var f=m.__[0];m.__=m.__N,m.__N=void 0,f!==m.__[0]&&(h=!0)}}),o){var p=o.call(this,l,u,c);return d?p||h:p}return!d||h};w.__f=!0;var o=w.shouldComponentUpdate,a=w.componentWillUpdate;w.componentWillUpdate=function(l,u,c){if(this.__e){var d=o;o=void 0,r(l,u,c),o=d}a&&a.call(this,l,u,c)},w.shouldComponentUpdate=r}return s.__N||s.__}function Ft(e,t){var n=Wt(xe++,3);!D.__s&&Ns(n.__H,t)&&(n.__=e,n.u=t,w.__H.__h.push(n))}function qt(e){return st=5,Kt(function(){return{current:e}},[])}function Kt(e,t){var n=Wt(xe++,7);return Ns(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function co(){for(var e;e=Ls.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(nt),t.__h.some(Ut),t.__h=[]}catch(n){t.__h=[],D.__e(n,e.__v)}}}D.__b=function(e){w=null,As&&As(e)},D.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),Es&&Es(e,t)},D.__r=function(e){Rs&&Rs(e),xe=0;var t=(w=e.__c).__H;t&&(Bt===w?(t.__h=[],w.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(nt),t.__h.some(Ut),t.__h=[],xe=0)),Bt=w},D.diffed=function(e){Ms&&Ms(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Ls.push(t)!==1&&Ts===D.requestAnimationFrame||((Ts=D.requestAnimationFrame)||po)(co)),t.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),Bt=w=null},D.__c=function(e,t){t.some(function(n){try{n.__h.some(nt),n.__h=n.__h.filter(function(s){return!s.__||Ut(s)})}catch(s){t.some(function(r){r.__h&&(r.__h=[])}),t=[],D.__e(s,n.__v)}}),Ps&&Ps(e,t)},D.unmount=function(e){Is&&Is(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(s){try{nt(s)}catch(r){t=r}}),n.__H=void 0,t&&D.__e(t,n.__v))};var Os=typeof requestAnimationFrame=="function";function po(e){var t,n=function(){clearTimeout(s),Os&&cancelAnimationFrame(t),setTimeout(e)},s=setTimeout(n,35);Os&&(t=requestAnimationFrame(n))}function nt(e){var t=w,n=e.__c;typeof n=="function"&&(e.__c=void 0,n()),w=t}function Ut(e){var t=w;e.__c=e.__(),w=t}function Ns(e,t){return!e||e.length!==t.length||t.some(function(n,s){return n!==e[s]})}function Hs(e,t){return typeof t=="function"?t(e):t}var uo=["none","minimal","low","medium","high","xhigh","max","ultra"],fo=["default","acceptEdits","plan","dontAsk","bypassPermissions","auto"];function js(e){return typeof e=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,127}$/.test(e)?e:null}function Bs(e,t){return typeof e=="string"&&t.includes(e)?e:null}function Vt(e={}){return{harness:js(e.harness),model:js(e.model),config:{effort:Bs(e.config?.effort,uo),permissionMode:Bs(e.config?.permissionMode,fo)},...typeof e.observedAt=="string"&&/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\.\\d{3}Z$/.test(e.observedAt)&&Number.isFinite(Date.parse(e.observedAt))?{observedAt:e.observedAt}:{}}}var J=e=>{if(!e)return"";let t=Math.max(0,(Date.now()-Date.parse(e))/1e3);return t<90?Math.round(t)+"s":t<5400?Math.round(t/60)+"m":t<172800?(t/3600).toFixed(1)+"h":Math.round(t/86400)+"d"},v=e=>i`<span data-age=${e??""}>${J(e)}</span>`;function H({worker:e,label:t,cls:n="badge"}){let s=Vt(e),r=[s.model??"model unknown",s.config.effort].filter(Boolean).join(" \\xB7 "),[o,a]=z(null),l=u=>{let c=u.currentTarget.getBoundingClientRect();a({left:Math.max(8,Math.min(c.left,window.innerWidth-280)),top:c.bottom+6})};return i`<span class=${n+" worker-harness"} tabindex="0" aria-label=${r}\n onMouseEnter=${l} onFocus=${l} onBlur=${()=>a(null)}\n onMouseLeave=${u=>{document.activeElement!==u.currentTarget&&a(null)}}\n onKeyDown=${u=>{u.key==="Escape"&&a(null)}}>\n ${t??s.harness??"unknown harness"}${o&&!g().modal&&i`<span class="worker-tooltip" role="tooltip" aria-hidden="true" style=${o}>${r}</span>`}\n </span>`}var zt=e=>e.worker&&i`<${H} worker=${e.worker} />`;function ot({worker:e,headless:t=!1}){let n=Vt(e);return i`<section class="worker-details"><div class="sec">${t?"headless worker \\xB7 launch / observation":"worker observation"}</div><dl>\n <dt>harness</dt><dd>${n.harness??"unknown"}</dd>\n <dt>model</dt><dd>${n.model??"model unknown"}</dd>\n <dt>effort</dt><dd>${n.config.effort??"unknown"}</dd>\n <dt>permission mode</dt><dd>${n.config.permissionMode??"unknown"}</dd>\n <dt>observed</dt><dd>${n.observedAt??"unknown"}</dd>\n </dl></section>`}var at=e=>e.activity&&i`<div class=${"activity"+(e.activity.stale?" stale":"")} title=${e.activity.stale?"no activity past the wedge threshold":e.activity.kind}>${e.activity.stale?"stale \\xB7 ":""}${e.activity.summary} \xB7 ${v(e.activity.at)} ago</div>`,mo=e=>e&&/^https?:\\/\\//i.test(e)?e:void 0,it=e=>{let t=e.waiting;if(!t)return;let n=mo(t.link),s=n;try{n&&(s=new URL(n).host+new URL(n).pathname.replace(/\\/$/,""))}catch{s=n}return i`<div class="waiting">${e.verb}: waiting on ${t.on} \xB7 ${v(t.since)}${n&&[" \\xB7 ",i`<a href=${n} target="_blank" rel="noopener noreferrer" onClick=${C}>${s}</a>`]}</div>`},ho=12,Us=e=>e!==void 0&&e.length>ho,j=e=>Us(e)?e:void 0,B=e=>Us(e)?" long":"",S=(e,t)=>()=>O(e,t),C=e=>e.stopPropagation();function Y(e){if(e.requested)return i`<span class="dim">Requested \u2014 no window yet</span>`;if(e.starting)return i`<span class="dim">${e.starting.failedAt?"Did not start":"Starting \\u2014 no window yet"}</span>`;if(ne(e)&&e.link)return Ge(e);if(!e.live)return Ge(e,"Resume:");let t=g();return!t.snapshot?.focusSupported&&!e.link?i`<span class="dim">Window focus is not supported here</span>`:i`<span class="winaction"><button class="btn open" title="open this trap\'s window" onClick=${s=>{C(s),ks(e.trapId)}}>\u2197 open</button>${e.link&&[" ",i`<a href=${e.link} onClick=${C}>Session link</a>`]}${t.focusResults[e.trapId]&&[" ",i`<span class="dim">${t.focusResults[e.trapId]}</span>`]}</span>`}function M(e,t,n){return t.length?i`<div class="wrap"><table><tbody><tr>${e.map(s=>i`<th>${s}</th>`)}</tr>${t}</tbody></table></div>`:i`<div class="empty">${n}</div>`}function ue({kind:e,more:t}){return!t.left&&!t.error?null:i`<div class="older">${t.left>0&&i`<button class="btn" disabled=${t.loading} onClick=${()=>{us(e)}}>${t.loading?"loading\\u2026":`show ${Math.min(t.left,50)} older (of ${t.left})`}</button>`}${t.error&&i` <span class="bad">${t.error}</span>`}</div>`}function go({text:e,label:t,href:n}){let[s,r]=z(null),o=l=>async u=>{C(u),await Ss(e)&&(r(l),setTimeout(()=>r(null),1e3))},a=[t&&i`<span class="dim">${t}</span>`,n?i`<code><a href=${n} onClick=${C}>${e}</a></code>`:i`<code class=${s==="code"?"copied":void 0} title="click to copy" onClick=${o("code")}>${e}</code>`,i`<button title="copy" onClick=${o("button")}>${s==="button"?"\\u2713":"\\u29C9"}</button>`];return t?i`<span class="cmd inline">${a}</span>`:i`<div class="cmd">${a}</div>`}var T=(e,t,n,s)=>i`<${go} key=${t} text=${e} label=${n} href=${s} />`,Ge=(e,t)=>{if(ne(e))return e.link?T(e.link,void 0,"desktop thread:",e.link):i`<span class="dim">desktop thread \u2014 open in the app</span>`;let n=Hn(e);return n?T(n,void 0,t):i`<span class="dim">Resume command unavailable</span>`},Ce=(e,t,n="thumb")=>i`<button\n type="button"\n class=${n}\n title=${"view "+t}\n onClick=${s=>{C(s),vs(e,t)}}\n >\n <img src=${e} alt=${t} loading="lazy" />\n </button>`,pe=(e,t)=>e.map(n=>[i`<div class="sub">${n.name} \xB7 ${n.type} \xB7 ${n.bytes} bytes</div>`,t&&Un(n.name)&&Ce(t(n.name),n.name),T(n.path)]),Ws=/\\bwt:([a-z0-9][a-z0-9-]*)/g,Jt=e=>g().snapshot?.trapNames?.[e],U=e=>e.replace(Ws,(t,n,s)=>{let r=Jt(n);return r&&!Fs(e,s,t.length,r)?r:t}),Fs=(e,t,n,s)=>e.slice(Math.max(0,t-s.length-2),t)===`${s} (`&&e[t+n]===")";function lt(e){let t="wt:"+e,n=Jt(e)??t;return g().snapshot?.traps.some(r=>r.trapId===e)?i`<a class="trapname" href="#traps" title=${t} onClick=${r=>{r.preventDefault(),C(r),O("trap",e)}}>${n}</a>`:i`<span class="trapname" title=${t}>${n}</span>`}var rt=e=>{let t=/^wt:([a-z0-9][a-z0-9-]*)$/.exec(e);return t?lt(t[1]):e};function R(e,t=1/0){let n=[],s=0;for(let l of e.matchAll(Ws)){l.index>s&&n.push({text:e.slice(s,l.index)});let u=Jt(l[1]);n.push(u&&Fs(e,l.index,l[0].length,u)?{text:l[0]}:{text:u??l[0],trapId:l[1]}),s=l.index+l[0].length}s<e.length&&n.push({text:e.slice(s)});let r=n.reduce((l,u)=>l+u.text.length,0),o=r>t?t-1:1/0,a=[];for(let l of n){if(o<=0)break;l.text.length<=o?a.push(l.trapId?lt(l.trapId):l.text):a.push(l.text.slice(0,o)),o-=l.text.length}return r>t&&a.push("\\u2026"),a}var $o=e=>e.log.flatMap((t,n)=>[n?`\n`:"",t.at+" "+t.verb,...t.note?[" ",...R(t.note)]:[]]),vo=e=>"brief"in e;function qs(e,t){let n=[e.elapsed&&`elapsed: ${e.elapsed}`,e.attempt&&`attempt: ${e.attempt}`,e.branch&&`branch: ${e.branch}`,e.lastCommit&&`last commit: ${e.lastCommit}`,e.aheadTrunk&&`commits: ${e.aheadTrunk}`,e.draftPr&&`draft PR: ${e.draftPr}`,e.updated&&`updated: ${e.updated}`].filter(Boolean).join(`\n`),s=i`${e.waiting&&[i`<div class="sec">waiting</div>`,it(e)]}${e.activity&&[i`<div class="sec">activity</div>`,at(e)]}${n&&[i`<div class="sec">progress</div>`,i`<pre>${n}</pre>`]}`,r=e.evidence&&{...e.evidence};return r?.worker&&(delete r.worker,delete r.harness),vo(e)?i`${s}<div class="sec">brief</div><pre>${e.brief}</pre>${e.attachments.length>0&&[i`<div class="sec">attachments (${e.attachments.length})</div>`,pe(e.attachments,o=>Rt(e.lane,e.id,o))]}${e.messageAttachments.length>0&&[i`<div class="sec">message attachments (${e.messageAttachments.length})</div>`,pe(e.messageAttachments,o=>Rt(e.lane,e.id,o))]}${e.followUp&&[i`<div class="sec">forks</div>`,i`<pre>${e.followUp}</pre>`]}<div class="sec">log</div><div class="loglines">${e.log.length?$o(e):"no entries yet"}</div>${e.inbox.length>0&&[i`<div class="sec">inbox</div>`,i`<div class="loglines">${e.inbox.join(`\n---\n`)}</div>`]}${e.awaitingReply&&[i`<div class="sec">awaiting reply</div>`,i`<div>${e.awaitingReply.line} \xB7 from ${e.awaitingReply.from} \xB7 ${v(e.awaitingReply.sentAt)} ago</div>`]}${r&&[i`<div class="sec">evidence</div>`,i`<div class="loglines">${JSON.stringify(r)}</div>`]}`:i`${s}<div class="sec">brief</div><div class=${t?.error?"bad":"dim"}>${t?.error??"loading\\u2026"}</div>${e.followUp&&[i`<div class="sec">forks</div>`,i`<pre>${e.followUp}</pre>`]}${e.note&&[i`<div class="sec">last note</div>`,i`<div class="loglines">${R(e.note)}</div>`]}`}function Te(e){return e.for?[rt(e.for),e.evidence&&e.evidence.deliveredTo?[" ",i`<span class="ok">\u2713delivered</span>`]:[" ",i`<span class="warn">waiting</span>`]]:e.claimedBy?rt(e.claimedBy):""}function fe(e){if(e.prList&&e.prList.length>1)return[e.prList.map((r,o)=>[o?" \\u2192 ":"",i`<a href=${r.url} target="_blank" rel="noopener" onClick=${C}>#${r.number}</a>`,r.badge&&[" ",i`<span class=${"badge "+E(r.badge)}>${r.badge.text}</span>`]]),e.prGate&&[" ",i`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]];let t=e.evidence&&(e.evidence.prUrl||e.evidence.pr&&e.evidence.pr.url);if(!t)return"";let n=e.prBadge,s=e.evidence&&e.evidence.prUrls&&e.evidence.prUrls.length>1?e.evidence.prUrls:void 0;return[s?s.map((r,o)=>[o?" ":"",i`<a href=${r} target="_blank" rel="noopener" onClick=${C}>#${r.split("/").pop()}</a>`]):i`<a href=${t} target="_blank" rel="noopener" onClick=${C}>PR</a>`,n&&[" ",i`<span class=${"badge "+E(n)} title=${"observed "+n.observedAt}>${n.text}</span>`],e.prGate&&[" ",i`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]]}var ko={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready","stack-ready":"stack ready",landed:"landed",watch:"watch"},Yt={"pr:review":"bad","pr:checks":"bad","pr:conflict":"pr-conflicts","pr:ready":"ok","stack-ready":"ok","pr:draft":"dim",watch:"warn"},Ks=e=>ko[e]||"";var dt=e=>i`<a href=${e.url} target="_blank" rel="noopener" onClick=${C}>#${e.number}</a>`,ct=e=>i`<span class="prname" title=${e.title||void 0}><b>#${e.number}</b>${e.title&&[" ",e.title]}</span>`;function me(e,t,n){return e.flatMap((s,r)=>{let o=t.get(s)||void 0,a=s===n?i`<b title=${o}>#${s}</b>`:i`<span title=${o}>#${s}</span>`;return r?[" \\u2192 ",a]:[a]})}function Ae(e){let t=e.checks;return t.passed+"/"+t.total+" passed"+(t.failed?" \\xB7 "+t.failed+" failed":"")+(t.pending?" \\xB7 "+t.pending+" pending":"")}function pt(e){let t=e.review||{};return(e.reviewDecision||"")+(t.unresolvedThreads?" \\xB7 "+t.unresolvedThreads+" unresolved":"")+(t.changesRequested?" \\xB7 changes requested":"")}function Re(e){return[e.mergeStateStatus,e.nextMergeable?[" \\xB7 ",i`<span class="ok">next mergeable</span>`]:e.blockedBy?" \\xB7 blocked by #"+e.blockedBy:""]}function Qt(e){let t=es(e);return e?[t.text," \\xB7 ",t.at?[v(t.at)," ago"]:"never checked"]:i`<span class="dim">${t.text}</span>`}function Me(e){if(e.requested)return{stale:!1,listen:[i`<span class="dot"></span>`,i`<span class="dim">requested</span>`],hb:i`<span class="dim">\u2014</span>`};if(e.starting)return{stale:!1,listen:e.starting.failedAt?[i`<span class="dot bad"></span>`,i`<span class="bad">start failed</span>`]:[i`<span class="dot warn"></span>`,"starting"],hb:i`<span class="dim">\u2014</span>`};if(!e.live)return{stale:!1,listen:[i`<span class="dot"></span>`,i`<span class="dim">signed off</span>`],hb:i`<span class="dim">\u2014</span>`};let t=Date.now()-Date.parse(e.heartbeatAt)>18e5,n=e.listening??(!!e.firstParkedAt&&!t);return{stale:t,listen:n?[i`<span class="dot ok"></span>`,"listening"]:[i`<span class="dot warn"></span>`,"not listening"],hb:i`<span class=${t?"bad":"ok"}>${t&&"stale "}${v(e.heartbeatAt)} ago</span>`}}function Xt(e){if(e.requested)return{kind:"requested",helmOn:!!g().snapshot?.helmOn};if(e.starting)return e.starting.failedAt?{kind:"start failed",reason:e.starting.reason??"no session signed on in time"}:{kind:"starting",deadline:e.starting.deadline};if(!e.live)return{kind:"signed off"};let t=e.claimed?e.catches.find(n=>n.id===e.claimed&&n.bucket==="active"):void 0;return t?t.waiting||t.verb==="paused"?{kind:"parked",current:t}:{kind:"working",current:t}:{kind:"idle",listening:e.listening??(!!e.firstParkedAt&&Date.now()-Date.parse(e.heartbeatAt??"")<=18e5)}}function bo(e){let t=Xt(e);return t.kind==="working"||t.kind==="idle"&&t.listening?"ok":t.kind==="start failed"?"bad":t.kind==="parked"||t.kind==="starting"?"warn":"dim"}var Vs=e=>e.waiting?`waiting on ${e.waiting.on}`:e.note||"waiting",zs=e=>e.title.slice(0,40)||"(no title)";function Pe(e){let t=Xt(e),n=i`<span class=${"dot trapdot "+bo(e)}></span>`;if(t.kind==="requested")return[n,i`<span class="dim">${Js(e,t.helmOn)}</span>`];if(t.kind==="starting")return[n,"starting \\xB7 waiting for its session to sign on"];if(t.kind==="start failed")return[n,i`<span class="bad">start failed</span>`," \\xB7 ",t.reason];if(t.kind==="signed off")return[n,i`<span class="dim">signed off</span>`];if(t.kind==="idle")return[n,"idle \\xB7 ",t.listening?"listening":"not listening"];let s=t.current;return t.kind==="parked"?[n,"parked \\xB7 ",Vs(s)]:[n,"working \\xB7 ",i`<a href="#dispatches" onClick=${o=>{o.preventDefault(),C(o),O("dispatch",`${s.lane}:${s.id}`)}}>${s.id.slice(0,8)}</a>`," \\xB7 ",zs(s),s.activity&&[" \\xB7 ",s.activity.summary," ",v(s.activity.at)," ago"]]}var Js=(e,t)=>`requested \\xB7 ${e.repo??""} \\xB7 ${e.harness??""} \\xB7 ${t?"waiting for the helm":"waiting for a helm"}`;function Q(e){let t=e.starting?.commands;return t?.length?i`<div class="startcmds" onClick=${C}><div class="dim">start it: run one in a terminal</div>${t.map(n=>T(n.command,n.harness))}</div>`:null}function ut(){let t=g().snapshot?.repoKeys??[],[n,s]=z(!1),[r,o]=z(""),[a,l]=z("claude"),[u,c]=z(null),d=r||t[0]||"",h=async p=>{p.preventDefault();let m=await bs(d,a);c(m??null),m||s(!1)};return n?i`<form class="newtrap" onClick=${C} onSubmit=${h}>\n <label>repo <select name="repo" value=${d} onChange=${p=>o(p.target.value)}>${t.map(p=>i`<option value=${p}>${p}</option>`)}</select></label>\n <label>harness <select name="harness" value=${a} onChange=${p=>l(p.target.value)}><option value="claude">claude</option><option value="codex">codex</option></select></label>\n <button class="btn" type="submit" disabled=${!d}>Request</button>\n <button class="btn" type="button" onClick=${()=>s(!1)}>Cancel</button>\n ${u&&i`<span class="bad">${u}</span>`}\n </form>`:i`<span class="newtrap"><button class="btn" onClick=${p=>(C(p),s(!0),c(null))}>+ New trap</button></span>`}function ft(e){let t=Xt(e);if(t.kind==="requested")return Js(e,t.helmOn);if(t.kind==="starting")return`starting \\xB7 sign-on due by ${t.deadline}`;if(t.kind==="start failed")return`start failed \\xB7 ${t.reason}`;if(t.kind==="signed off")return"signed off";if(t.kind==="idle")return`idle \\xB7 ${t.listening?"listening":"not listening"}`;if(t.kind==="parked")return`parked \\xB7 ${Vs(t.current)}`;let n=t.current;return[`working \\xB7 ${n.id.slice(0,8)} \\xB7 ${zs(n)}`,n.activity&&`${n.activity.summary} ${J(n.activity.at)} ago`].filter(Boolean).join(" \\xB7 ")}function Zt(e){let t=e.messages.filter(n=>n.state==="pending").length;return e.messages.length?["\\u2709 "+e.messages.length,t>0&&[" ",i`<span class="warn">(${t} pending)</span>`]]:null}var yo=e=>()=>{window.open(G(e.key),"_blank","noopener")};function en(e){let t=ke(e);return{nodes:[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked?" \\xB7 acked":""],text:[t,`${J(e.filedAt)} ago`,e.acked?"acked":""].filter(Boolean).join(" \\xB7 ")}}function _o(e){let t=en(e);return i`<a key=${e.key} class=${"card"+(e.acked?" acked":"")} href=${G(e.key)} target="_blank" rel="noopener"><div class="top"><b title=${e.title}>${e.title}</b></div><div class="meta" title=${t.text}>${t.nodes}</div></a>`}function wo(e){return i`<tr key=${e.key} class=${"rowhead"+(e.acked?" acked":"")} onClick=${yo(e)}><td class="grow"><a href=${G(e.key)} target="_blank" rel="noopener" onClick=${t=>t.stopPropagation()}>${e.title}</a></td><td>${ke(e)}</td><td>${v(e.filedAt)}</td><td>${e.acked?"acked":""}</td></tr>`}function Ys({inp:e}){return e.view==="cards"?e.list.length?i`<div class="cards">${e.list.map(_o)}</div>`:i`<div class="empty">no reports match</div>`:M(["title","from","filed","acked"],e.list.map(wo),"no reports match")}function Zs(e){let t=e.trim();return/^(https?:\\/\\/|mailto:|#)/i.test(t)?t:void 0}function er(e){let t=e.trim();return/^[^/\\\\:?#]+$/.test(t)&&t!=="."&&t!==".."?t:void 0}function Qs(e,t,n,s){let r=0;for(let o=t;o<e.length;o++){if(e[o]==="\\\\"){o++;continue}if(e[o]===n)r++;else if(e[o]===s){if(r===0)return o;r--}}return-1}function Xs(e,t){let n=Qs(e,t+1,"[","]");if(n<0||e[n+1]!=="(")return;let s=Qs(e,n+2,"(",")");if(s<0)return;let r=e.slice(n+2,s).trim().replace(/\\s+"[^"]*"$/,"").replace(/^<(.*)>$/,"$1");return{text:e.slice(t+1,n),target:r,end:s+1}}function F(e){let t=[],n="",s=()=>{n&&t.push({t:"text",v:n}),n=""};for(let r=0;r<e.length;){let o=e[r];if(o==="\\\\"&&r+1<e.length&&/[\\\\`*_{}[\\]()#+\\-.!|<>~]/.test(e[r+1])){n+=e[r+1],r+=2;continue}if(o==="`"){let a=/^`+/.exec(e.slice(r))[0],l=e.indexOf(a,r+a.length);if(l>0){s(),t.push({t:"code",v:e.slice(r+a.length,l).replace(/^ (.*) $/,"$1")}),r=l+a.length;continue}}if(o==="!"&&e[r+1]==="["){let a=Xs(e,r+1);if(a){s(),t.push({t:"img",alt:a.text,src:a.target}),r=a.end;continue}}if(o==="["){let a=Xs(e,r);if(a){s(),t.push({t:"a",href:a.target,c:F(a.text)}),r=a.end;continue}}if((o==="*"||o==="_")&&e[r+1]===o){let a=e.indexOf(o+o,r+2);if(a>r+2){s(),t.push({t:"b",c:F(e.slice(r+2,a))}),r=a+2;continue}}if(o==="*"||o==="_"&&(r===0||!/\\w/.test(e[r-1]))){let a=r+1;for(;(a=e.indexOf(o,a))>0&&(e[a+1]===o||o==="_"&&/\\w/.test(e[a+1]??""));)a+=2;if(a>r+1&&e[r+1]!==" "){s(),t.push({t:"i",c:F(e.slice(r+1,a))}),r=a+1;continue}}if(o===`\n`){/ {2,}$/.test(n)||n.endsWith("\\\\")?(n=n.replace(/( {2,}|\\\\)$/,""),s(),t.push({t:"br"})):n+=" ",r++;continue}n+=o,r++}return s(),t}var tr=/^ {0,3}(`{3,}|~{3,})\\s*([^`\\s]*)/,nr=/^ {0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/,sr=/^ {0,3}([-*_])(\\s*\\1){2,}\\s*$/,sn=/^( {0,3})([-*+])\\s+(.*)$/,rn=/^( {0,3})(\\d{1,9})[.)]\\s+(.*)$/,mt=/^ {0,3}>\\s?(.*)$/,So=/^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;function tn(e){let t=e.trim();t.startsWith("|")&&(t=t.slice(1)),t.endsWith("|")&&!t.endsWith("\\\\|")&&(t=t.slice(0,-1));let n=[],s="";for(let r=0;r<t.length;r++)t[r]==="\\\\"&&t[r+1]==="|"?(s+="|",r++):t[r]==="|"?(n.push(s.trim()),s=""):s+=t[r];return n.push(s.trim()),n}var nn=e=>tr.test(e)||nr.test(e)||sr.test(e)||sn.test(e)||rn.test(e)||mt.test(e);function ht(e){let t=e.replace(/\\r\\n?/g,`\n`).replace(/\\t/g," ").split(`\n`),n=[],s=0;for(;s<t.length;){let r=t[s];if(!r.trim()){s++;continue}let o=tr.exec(r);if(o){let d=o[1],h=[];for(s++;s<t.length&&!new RegExp(`^ {0,3}${d[0]}{${d.length},}\\\\s*$`).test(t[s]);)h.push(t[s++]);s++,n.push({t:"code",lang:o[2]??"",v:h.join(`\n`)});continue}let a=nr.exec(r);if(a){n.push({t:"h",level:a[1].length,c:F(a[2])}),s++;continue}if(sr.test(r)){n.push({t:"hr"}),s++;continue}if(mt.test(r)){let d=[];for(;s<t.length&&t[s].trim()&&(mt.test(t[s])||!nn(t[s]));)d.push(mt.exec(t[s])?.[1]??t[s]),s++;n.push({t:"quote",c:ht(d.join(`\n`))});continue}let l=sn.exec(r),u=rn.exec(r);if(l||u){let d=!l,h=d?rn:sn,p=[];for(;s<t.length;){let m=t[s],f=h.exec(m);if(f&&f[1].length<=3){p.push([f[3]]),s++;continue}if(!m.trim()){if(s+1<t.length&&/^ {2,}\\S/.test(t[s+1])){p.at(-1).push(""),s++;continue}break}if(/^ {2,}\\S/.test(m)){p.at(-1).push(m.replace(/^ {2,4}/,"")),s++;continue}if(nn(m))break;p.at(-1).push(m.trim()),s++}n.push({t:"list",ordered:d,start:d?Number(u[2]):1,items:p.map(m=>ht(m.join(`\n`)))});continue}if(r.includes("|")&&s+1<t.length&&So.test(t[s+1])&&t[s+1].includes("-")){let d=tn(r),h=tn(t[s+1]).map(m=>m.startsWith(":")&&m.endsWith(":")?"center":m.endsWith(":")?"right":m.startsWith(":")?"left":"");s+=2;let p=[];for(;s<t.length&&t[s].trim()&&t[s].includes("|");){let m=tn(t[s++]);p.push(d.map((f,$)=>F(m[$]??"")))}n.push({t:"table",align:d.map((m,f)=>h[f]??""),head:d.map(F),rows:p});continue}let c=[];for(;s<t.length&&t[s].trim()&&!nn(t[s])&&!(c.length&&/^ {0,3}(=+|-+)\\s*$/.test(t[s]));)c.push(t[s++].replace(/^ +/,""));if(c.length===0){n.push({t:"p",c:F(r.trim())}),s++;continue}n.push({t:"p",c:F(c.join(`\n`))})}return n}function q(e,t){return t.map(n=>{switch(n.t){case"text":return n.v;case"code":return i`<code>${n.v}</code>`;case"b":return i`<strong>${q(e,n.c)}</strong>`;case"i":return i`<em>${q(e,n.c)}</em>`;case"br":return i`<br />`;case"a":{let s=Zs(n.href);return s?i`<a href=${s} target="_blank" rel="noopener noreferrer">${q(e,n.c)}</a>`:q(e,n.c)}case"img":{let s=er(n.src);return s?Ce(e(s),n.alt||s,"mdimg"):i`<span class="dim">[image not shown: ${n.alt||n.src}]</span>`}}})}function gt(e,t){return t.map(n=>{switch(n.t){case"h":{let s=q(e,n.c);return n.level===1?i`<h1>${s}</h1>`:n.level===2?i`<h2>${s}</h2>`:n.level===3?i`<h3>${s}</h3>`:i`<h4>${s}</h4>`}case"p":return i`<p>${q(e,n.c)}</p>`;case"code":return i`<pre class="mdcode"><code>${n.v}</code></pre>`;case"hr":return i`<hr />`;case"quote":return i`<blockquote>${gt(e,n.c)}</blockquote>`;case"list":{let s=n.items.map(r=>i`<li>${gt(e,r)}</li>`);return n.ordered?i`<ol start=${n.start}>${s}</ol>`:i`<ul>${s}</ul>`}case"table":return i`<div class="mdtable"><table><thead><tr>${n.head.map((s,r)=>i`<th style=${n.align[r]?"text-align:"+n.align[r]:void 0}>${q(e,s)}</th>`)}</tr></thead><tbody>${n.rows.map(s=>i`<tr>${s.map((r,o)=>i`<td style=${n.align[o]?"text-align:"+n.align[o]:void 0}>${q(e,r)}</td>`)}</tr>`)}</tbody></table></div>`}})}var Ie=new Map;function rr(e){let t=Ie.get(e);return t||(t=ht(e),Ie.set(e,t),Ie.size>8&&Ie.delete(Ie.keys().next().value)),t}function Do({r:e,text:t}){let n=t?.text!==void 0?gt(s=>Pt(e.key,s),rr(t.text)):t?.error?i`<div class="bad">${t.error}</div>`:i`<div class="dim">loading\u2026</div>`;return i`<div class="mdpage" data-report=${e.key}>${n}</div>`}function or({text:e,fileUrl:t}){return i`<div class="mdpage">${gt(t,rr(e))}</div>`}function on(e){let t=ke(e);return[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked&&[" \\xB7 ",i`<span class="ok">acked</span>`]]}function ar({r:e,text:t,heading:n}){return[n&&i`<div class="sec">report \xB7 ${e.title}</div>`,i`<div class="sub">${on(e)}</div>`,i`<${Do} r=${e} text=${t} />`,e.attachments.length>0&&[i`<div class="sec">report attachments (${e.attachments.length})</div>`,pe(e.attachments,s=>Pt(e.key,s))],!e.acked&&[i`<div class="sec">ack</div>`,T("lobstah attention ack "+e.key)]]}var xo=/\\.(png|jpe?g|gif|webp)$/i,Go=e=>{e.style.height="auto",e.style.height=e.scrollHeight+"px"};function Co(e,t){return t.length?i`<div class="dfiles">${t.map(n=>xo.test(n.name)?i`<span key=${n.name}>${Ce(Mt(e,n.name),n.name,"dimg")}</span>`:i`<div key=${n.name} class="dfile"><span>${n.name}</span> <span class="dim">\xB7 ${n.type} \xB7 ${n.bytes} bytes \xB7 </span><code>${n.path}</code></div>`)}</div>`:null}function To(e,t,n){let s=e.key,r=e.kind==="decision"?e.options:[],o=t?.text??"",a=t?.files??[],l=!!t?.sending,u=d=>d+1<=Se?String(d+1):void 0,c=u(r.length);return[r.length>0&&i`<div class="doptions">${r.map((d,h)=>{let p=u(h);return i`<button key=${d} type="button" class=${"btn dopt"+(t?.option===d?" on":"")} aria-pressed=${t?.option===d?"true":"false"} aria-keyshortcuts=${p} disabled=${l} onClick=${()=>ms(s,d)}>${p&&i`<kbd class="dkey" aria-hidden="true">${p}</kbd>`}<span class="dlabel">${d}</span></button>`})}</div>`,i`<div class="danswer-wrap">${c&&i`<kbd class="dkey dkey-text" aria-hidden="true">${c}</kbd>`}<textarea\n class="danswer"\n rows="2"\n aria-keyshortcuts=${c}\n aria-label=${r.length?"Your answer, in your own words":"Your answer"}\n placeholder=${r.length?"Add to your answer, or answer in your own words":"Your answer"}\n value=${o}\n disabled=${l}\n onInput=${d=>{let h=d.currentTarget;Go(h),A(s,{text:h.value,error:void 0})}}\n onPaste=${d=>{hs(s,d)}}\n ></textarea></div>`,i`<div class="dfoot">\n <label class="btn dattach" title="attach images or files">attach<input type="file" multiple accept=${n} disabled=${l} onChange=${d=>{let h=d.currentTarget;jt(s,h.files).then(()=>{h.value=""})}} /></label>\n ${a.map((d,h)=>i`<span key=${d.name+h} class="dchip">${d.name}<button type="button" class="dx" title="remove" disabled=${l} onClick=${()=>gs(s,h)}>\xD7</button></span>`)}\n ${t?.error&&i`<span class="bad derr">${t.error}</span>`}\n <button type="button" class="btn dsend" disabled=${l} onClick=${()=>{tt(s)}}>${l?"Sending\\u2026":"Send"}</button>\n </div>`]}var ir=e=>e.kind==="decision"?e.title:R(e.note);function Ao(e,t,n){return t?.sent?"answered":e.viewedAt||n?"read":"unread"}function an(e){let t=e.dispatch,n=e.lane??"work";return[t&&i`<a class="dlink" href="#" onClick=${r=>{r.preventDefault(),r.stopPropagation(),S("dispatch",n+":"+t)()}}>${t.slice(0,8)}</a>`,e.repo].filter(Boolean).flatMap((r,o)=>o?[" \\xB7 ",r]:[r])}function Ro(e,t,n,s){let r=Ao(e,t,n),o=()=>ie(e.key);return i`<li key=${e.key} class=${"drow "+r+(s?" focus":"")} data-decision=${e.key}>\n <button type="button" class="dopen" onClick=${o} aria-label=${`${r}: ${e.kind==="decision"?e.title:e.note}`}>\n ${e.kind==="question"&&i`<span class=${"badge "+(e.verb==="blocked"?"bad":"warn")}>${e.verb}</span>`}\n <b class="dtitle">${ir(e)}</b>\n </button>\n <span class="dmeta dim">${an(e)}</span>\n <span class="dage dim">${v(e.at)} ago</span>\n <span class=${"dstate "+r}>${r==="answered"?`answered \\xB7 ${t.sent}`:r}</span>\n </li>`}function lr({cards:e,drafts:t,focus:n,viewedHere:s,unread:r}){let o=e.length?i`<ul class="dlist">${e.map(a=>Ro(a,t[a.key],!!s[a.key],a.key===n))}</ul>`:i`<div class="empty">none</div>`;return i`<section class="decisions"><h2>decisions${r>0&&i`<span class="dbadge" aria-label=${`${r} new`}>${r}</span>`}</h2>${o}</section>`}function Mo(e){let t=Math.min(e,Se),n=e+1<=Se?String(e+1):void 0,s=[t>0&&[i`<kbd>1</kbd>`,t>1&&["\\u2013",i`<kbd>${t}</kbd>`]," choose"],n&&[i`<kbd>${n}</kbd>`," write"],t>0&&[i`<kbd>Enter</kbd>`," on a chosen option sends"],[i`<kbd>\u2190</kbd>`," ",i`<kbd>\u2192</kbd>`," previous / next"],[i`<kbd>Esc</kbd>`," leaves the text box, then closes"],[i`<kbd>d</kbd>`," opens decisions anywhere"]].filter(Boolean);return i`<div class="dlegend dim">${s.flatMap((r,o)=>o?[" \\xB7 ",r]:[r])}</div>`}var Po=\'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])\';function dr({open:e,order:t,drafts:n,extensions:s}){let r=qt(null),o=qt(null),a=!!e;Ft(()=>{if(a)return o.current=document.activeElement,r.current?.focus(),()=>{let m=o.current;m&&typeof m.focus=="function"&&document.contains(m)&&m.focus()}},[a]);let l=e?.key??null;if(Ft(()=>{l&&ds(l)},[l]),!e)return null;let u=m=>{if(m.key!=="Tab"||!r.current)return;let f=[...r.current.querySelectorAll(Po)];if(!f.length)return void m.preventDefault();let $=f[0],_=f[f.length-1];m.shiftKey&&(document.activeElement===$||document.activeElement===r.current)?(m.preventDefault(),_.focus()):!m.shiftKey&&document.activeElement===_&&(m.preventDefault(),$.focus())},c=l?t.find(m=>m.key===l):void 0,d=c?t.indexOf(c):-1,h=(m,f,$="")=>i`<div id="doverlay" class="open" onClick=${_=>_.target===_.currentTarget&&le()}>\n <div class="modal dmodal" role="dialog" aria-modal="true" aria-labelledby="dmodal-title" tabindex="-1" ref=${r} onKeyDown=${u} data-decision=${$}>\n <button type="button" class="x" aria-label="close" aria-keyshortcuts="Escape" onClick=${le}>\xD7</button>\n <h3 id="dmodal-title" class="sr-only">${m}</h3>\n ${f}\n </div>\n </div>`;if(!c)return h("All decisions answered",i`<div class="ddone" onClick=${le}><div class="ok">\u2713 All decisions answered.</div><div class="dim">Click anywhere or press Escape to close.</div></div>`);let p=n[c.key];return h(c.kind==="decision"?c.title:c.note,i`<div class="dnav">\n <button type="button" class="btn dprev" aria-label="previous decision" aria-keyshortcuts="ArrowLeft" disabled=${d<=0} onClick=${()=>we(-1)}>\u2039 prev</button>\n <span class="dpos" aria-live="polite">${d+1} of ${t.length}</span>\n <button type="button" class="btn dnext" aria-label="next decision" aria-keyshortcuts="ArrowRight" disabled=${d>=t.length-1} onClick=${()=>we(1)}>next \u203A</button>\n </div>\n <div class="dtop">\n ${c.kind==="question"&&i`<span class=${"badge "+(c.verb==="blocked"?"bad":"warn")}>${c.verb}</span>`}\n <b class="dtitle">${ir(c)}</b>\n <span class="dmeta dim">${an(c)}${an(c).length?" \\xB7 ":""}${v(c.at)} ago</span>\n </div>\n ${c.kind==="decision"&&c.detail.trim()&&i`<${or} text=${c.detail} fileUrl=${m=>Mt(c.key,m)} />`}\n ${c.kind==="decision"&&Co(c.key,c.attachments)}\n ${p?.sent?i`<div class="danswered ok">answered \xB7 ${p.sent}</div>`:To(c,p,s.join(","))}\n ${Mo(c.kind==="decision"?c.options.length:0)}`,c.key)}function cr({unread:e,dismissed:t}){let n=e.some(a=>!t.includes(a.key)),s=e.length>0&&n,r=e.length,o=`${r} new decision${r===1?"":"s"}`;return i`<div class="dalert-live" role="status" aria-live="polite">${s&&i`<div class="dalert">\n <button type="button" class="dalert-open" aria-keyshortcuts="d" onClick=${()=>ie()}><span class="dcount" aria-hidden="true">${r}</span> <span>${o}</span></button>\n <button type="button" class="dx" aria-label="dismiss" title="dismiss" onClick=${cs}>\xD7</button>\n </div>`}</div>`}function Lo(e,t){let n=e.badge&&(e.badge.worker?i`<${H} worker=${e.badge.worker} label=${e.badge.text} cls=${"badge "+(e.badge.tone||"dim")} />`:i`<span class=${"badge "+(e.badge.tone||"dim")+B(e.badge.text)} title=${j(e.badge.text)}>${e.badge.text}</span>`),s=e.worker&&i`<${H} worker=${e.worker} />`;if(e.href){let r=(t==="cards"?"card":"deckline click")+(e.acked?" acked":"");return t==="cards"?i`<a key=${e.key} class=${r} href=${e.href} target="_blank" rel="noopener"><div class="top"><b>${e.title}</b>${n}</div>${e.meta&&i`<div class="meta" title=${e.metaText}>${e.meta}</div>`}</a>`:i`<a key=${e.key} class=${r} href=${e.href} target="_blank" rel="noopener">${n&&[n," "]}<b>${e.title}</b>${e.meta&&[" ",i`<span class="dim">\xB7 ${e.meta}</span>`]}</a>`}return t==="cards"?i`<div key=${e.key} class=${"card"+(e.acked?" acked":"")} onClick=${e.open} style=${e.open?void 0:"cursor:default"}><div class="top"><b>${e.title}</b>${s}${n}</div>${e.meta&&i`<div class="meta" title=${e.metaText}>${e.meta}</div>`}${e.extra}${e.action&&i`<div class="foot"><span class="footact">${e.action}</span></div>`}</div>`:i`<div key=${e.key} class=${"deckline"+(e.open?" click":"")+(e.acked?" acked":"")} onClick=${e.open}>${n&&[n," "]}<b>${e.title}</b>${s&&[" ",s]}${e.meta&&[" ",i`<span class="dim">\xB7 ${e.meta}</span>`]}${e.action&&[" ",i`<span class="dim">\xB7 </span>`,e.action]}${e.extra}</div>`}var pr=(e,t)=>e>0&&i`<a class="deckmore" href=${"#"+t}>+${e} more \u2192</a>`;function $t(e,t,n,s,r,o){let a=t.slice(0,s),l=a.map(c=>Lo(c,r)),u=a.length?r==="cards"?i`<div class="cards">${l}</div>`:l:i`<div class="empty">none</div>`;return i`<section><h2><a href=${"#"+n}>${e} \u2192</a></h2>${o&&i`<div class="tabhead">${o}</div>`}${u}${pr(t.length-a.length,n)}</section>`}function No(e,t,n,s){let r=t.find(c=>c.number===e.nextNumber)||t[0],o=me(e.numbers,new Map(t.map(c=>[c.number,c.title]))),a=r?"next #"+r.number:"nothing mergeable";if(s==="cards"){let c=d=>{let h=n.get(d.key)||[],p=h.length>0&&h.every($=>$.acked),m=h.length?h.map($=>i`<span class=${"badge "+(Yt[$.kind]||"dim")}>${Ks($.kind)}</span>`):i`<span class=${"badge "+E(d.badge)+B(d.badge.text)} title=${j(d.badge.text)}>${d.badge.text}</span>`,f=`${d.repo} \\xB7 ${d.badge.text}${p?" \\xB7 acked":""}`;return i`<div key=${d.key} class=${"card"+(p?" acked":"")} onClick=${S("pr",d.key)}><div class="top">${ct(d)}${m}</div><div class="meta" title=${f}>${f}</div></div>`};return i`<div key=${e.id} class="deckstack"><div class="dim">${o} \xB7 ${a}</div>${e.readiness&&i`<div class=${e.readiness.allReady?"ok":"dim"}>${e.readiness.text}</div>`}<div class="cards">${t.map(c)}</div></div>`}let l=t.flatMap(c=>(n.get(c.key)||[]).map(d=>i`<span class=${"badge "+(Yt[d.kind]||E(c.badge))+(d.acked?" acked":"")}>#${c.number} ${c.badge.text}</span>`)),u=l.flatMap((c,d)=>d?[" ",c]:[c]);return i`<div key=${e.id} class=${"deckline"+(r?" click":"")} onClick=${r&&S("pr",r.key)}><b>${o}</b> <span class="dim">\xB7 ${a}</span>${l.length>0&&[" \\xB7 ",u]}${e.readiness&&i`<div class=${e.readiness.allReady?"ok":"dim"}>${e.readiness.text}</div>`}</div>`}function Ho(e,t){let n=e.stacks.slice(0,3),s=new Map;for(let o of e.prAttention){let a=s.get(o.key)||[];a.push(o),s.set(o.key,a)}let r=n.length?n.map(o=>No(o,e.prs.filter(a=>a.stackId===o.id).sort((a,l)=>a.position-l.position),s,t)):i`<div class="empty">none</div>`;return i`<section><h2><a href="#prs">PRs \u2192</a></h2>${r}${pr(e.stacks.length-n.length,"prs")}</section>`}function ur({inp:e,drafts:t,focus:n,viewedHere:s,unread:r}){let o=e.view,a=e.inflight.map(d=>({key:d.lane+":"+d.id,title:[d.id.slice(0,8)," ",d.repo||""],worker:d.worker,badge:{text:d.verb,tone:d.verb==="needs-decision"||d.verb==="blocked"?"bad":"dim"},meta:[R(d.note||"",90),d.verbAt&&[" \\xB7 ",v(d.verbAt)," ago"],(d.for||d.claimedBy)&&[" \\xB7 ",rt(d.for||d.claimedBy)]],metaText:[U(d.note||""),d.verbAt&&`${J(d.verbAt)} ago`,U(d.for||d.claimedBy||"")].filter(Boolean).join(" \\xB7 "),open:S("dispatch",d.lane+":"+d.id)})),l=e.landed.map(d=>({key:d.key,title:[d.id.slice(0,8)," ",d.repo||"",d.unreported&&[" ",i`<span class="badge warn unreported">unreported</span>`]],badge:{text:d.verb,tone:d.verb==="failed"?"bad":"ok"},meta:[R(d.note||"",90)," \\xB7 ",v(d.at)," ago"],metaText:`${U(d.note||"")} \\xB7 ${J(d.at)} ago`,open:S("dispatch",d.lane+":"+d.id)})),u=e.reports.map(d=>{let h=en(d);return{key:d.key,title:d.title,meta:h.nodes,metaText:h.text,href:G(d.key),acked:!!d.acked}}),c=e.traps.map(({x:d})=>({key:d.trapId,title:"\\u{1FAA4} "+(d.label??`wt:${d.trapId}`),badge:d.requested?{text:"requested",tone:"dim"}:d.starting?{text:d.starting.failedAt?"start failed":"starting",tone:d.starting.failedAt?"bad":"warn"}:{text:d.live?d.harness||"live":"signed off",tone:d.live?"ok":"dim",worker:d.live?d:void 0},meta:[d.repo||""," \\xB7 ",i`<span class="catchn" title="catches">\u{1F99E} ${te(d.totalCatches??0)}</span>`," \\xB7 ",Pe(d)],metaText:`${d.repo||""} \\xB7 \\u{1F99E} ${te(d.totalCatches??0)} \\xB7 ${ft(d)}`,action:Y(d),extra:Q(d),open:S("trap",d.trapId)}));return i`<div class="deckgrid"><${lr} cards=${e.decisions} drafts=${t} focus=${n} viewedHere=${s} unread=${r} />${$t("in flight",a,"dispatches",4,o)}${$t("Landed \\xB7 24h",l,"dispatches",8,o)}${$t("reports",u,"reports",8,o)}${$t("traps",c,"traps",8,o,i`<${ut} />`)}${Ho(e,o)}</div>`}function jo(e,t){if(!t)return e;let n=new Map(e.map(o=>[o.id,o])),s=o=>{let a=o,l=new Set;for(;a.followUp&&n.has(a.followUp)&&!l.has(a.id);)l.add(a.id),a=n.get(a.followUp);return a.id},r=new Map;for(let o of e){let a=s(o),l=r.get(a)||[];l.push(o),r.set(a,l)}return[...r.values()].sort((o,a)=>a[0].sort-o[0].sort).flatMap(o=>o.sort((a,l)=>a.id===s(a)?-1:l.id===s(l)?1:a.sort-l.sort))}function Bo(e,t){let n=e.lane+":"+e.id;return i`<tr key=${n} class="rowhead" onClick=${S("dispatch",n)}><td>${t&&e.followUp&&i`<span class="dim">\u21B3 </span>`}${e.id.slice(0,8)}</td><td>${e.lane} / ${e.bucket}</td><td>${e.repo}</td><td class=${"v-"+e.verb}>${e.verb}</td><td class="grow">${R(e.note??"",90)}${it(e)}${zt(e)}${at(e)}</td><td>${v(e.verbAt)}</td><td>${Te(e)}</td><td>${fe(e)}</td></tr>`}function Uo(e){let t=e.lane+":"+e.id;return i`<div key=${t} class="card" onClick=${S("dispatch",t)}><div class="top"><b>${e.id.slice(0,8)}</b>${zt(e)}<span class=${"badge v-"+e.verb+B(e.verb)} title=${j(e.verb)}>${e.verb}</span></div><div class="meta" title=${`${e.repo} \\xB7 ${e.lane} ${e.bucket}`}>${e.repo} \xB7 ${e.lane} ${e.bucket}${e.verbAt&&[" \\xB7 ",v(e.verbAt)]}</div>${e.note&&i`<div class="note" title=${U(e.note)}>${R(e.note)}</div>`}${it(e)}${at(e)}<div class="foot">${Te(e)} ${fe(e)}</div></div>`}function fr({inp:e,more:t}){let n=e.list,s=t&&i`<${ue} kind="dispatches" more=${t} />`;return e.view==="cards"?[n.length?i`<div class="cards">${n.map(Uo)}</div>`:i`<div class="empty">no dispatches match</div>`,s]:[M(["id","lane / bucket","repo","verb","note","age","addressed","pr"],jo(n,e.chain).map(r=>Bo(r,e.chain)),"no dispatches match"),s]}var Wo={deck:"On deck",dispatches:"Dispatches",traps:"Traps",prs:"PRs",reports:"Reports",notices:"Notices",stats:"Stats"},Fo=["working","needs-decision","blocked","paused","done","failed","unknown"],mr=(e,t)=>i`<span role="img" aria-label=${t} title=${t}>${e}</span>`;function qo(e,t){let n=t.daemonStale,s=e.daemon?[i`<span class=${n?"bad":"ok"}>${n&&"stale "}${v(e.daemon.heartbeat)} ago</span>`," ",i`<span class="dim">v${e.daemon.version}</span>`]:i`<span class="bad">down</span>`;return[i`<span class="chip">daemon ${s}</span>`,t.stats&&i`<span class="chip" title="catches today">\u{1F99E} ${t.stats.catchesToday} today</span>`,e.slots&&i`<span class="chip">active ${mr("\\u{1F3A3}","headless")} ${e.slots.headless} of ${e.slots.limit}; ${mr("\\u{1FAA4}","traps")} ${e.slots.traps}${e.slots.parked?`; parked: ${e.slots.parked} (no slot)`:""}</span>`,t.helms.map(({x:r,stale:o})=>i`<span key=${r.grounds} class="chip click" onClick=${S("helm",r.grounds)}>\u26F5 <${H} worker=${r} label=${i`<b>${r.man}</b>`} cls="" /> <span class="dim">helm ${r.grounds}</span> <span class=${o?"warn":"ok"}>${o&&"stale "}${v(r.heartbeatAt)} ago</span></span>`)]}var ln=[];function Ko(e){let t=[...new Set([...e.dispatches.map(n=>n.repo),...e.notices.map(n=>n.repo),...e.prs.map(n=>n.repo)].filter(Boolean))].sort();return t.length!==ln.length&&(ln=t),ln}var dn=[];function Vo(e){let t=[...new Set(e.notices.map(n=>n.kind))].sort();return t.length!==dn.length&&(dn=t),dn}var Ee=e=>e.currentTarget.value;function zo(e,t,n){let s=a=>t===a?"":"display:none",r=e?Ko(e):[],o=e?Vo(e):[];return i`<div class="controls" style=${t==="stats"?"display:none":void 0}>\n <select id="f-lane" style=${e&&s("dispatches")} value=${n.lane} onChange=${a=>N({lane:Ee(a)})}>\n <option value="">all lanes</option>\n <option value="work">work</option>\n <option value="chore">chore</option>\n </select>\n <select id="f-repo" value=${n.repo} onChange=${a=>N({repo:Ee(a)})}>\n <option value="">all repos</option>\n ${r.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <select id="f-verb" style=${e&&s("dispatches")} value=${n.verb} onChange=${a=>N({verb:Ee(a)})}>\n <option value="">all verbs</option>\n ${Fo.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <label id="chain-control" style=${e&&s("dispatches")}><input id="f-chain" type="checkbox" checked=${!!n.chain} onChange=${a=>N({chain:a.currentTarget.checked})} /> group by chain</label>\n <select id="f-kind" style=${e&&s("notices")} value=${n.noticeKind} onChange=${a=>N({noticeKind:Ee(a)})}>\n <option value="">all notice kinds</option>\n ${o.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <input id="f-q" type="search" placeholder="search id \xB7 note \xB7 brief" value=${n.q} onInput=${a=>N({q:Ee(a)})} />\n </div>`}function hr({d:e,inp:t,tab:n,st:s,stale:r,unread:o=0}){return[i`<div class="headerline"><h1>\u{1F99E}\u2728 spyglass<span id="stale" style=${e||r?r?"display:inline":"display:none":void 0}> \xB7 STALE FEED</span></h1><span id="settings-slot"><button id="gearbtn" title="settings" aria-label="settings" onClick=${()=>O("settings","browser")}>\u2699</button></span></div>`,i`<div class="chips"><span id="chips" style="display:contents">${e&&t&&qo(e,t.chips)}</span><span class="chip dim" id="clock">${e&&new Date(e.now).toLocaleTimeString("en-GB")}</span></div>`,i`<nav class="tabs" id="tabs" aria-label="Spyglass views">${se.map(a=>i`<a href=${"#"+a} data-tab=${a} class=${e?a===n?"on":"":void 0}>${Wo[a]}${a==="deck"&&o>0&&i`<span class="dbadge" aria-label=${`${o} new decision${o===1?"":"s"}`}>${o}</span>`}</a>`)}</nav>`,zo(e,n,s)]}var gr=({d:e})=>e&&["\\u{1F99E}\\u2728 lobstah v"+e.version+" \\xB7 ",i`<a href=${e.repoUrl} target="_blank">${e.repoUrl.replace("https://github.com/","")}</a>`];function $r(e,t){if(!t.lobs)return[];let n={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready","stack-ready":"stack ready",landed:"landed",watch:"watch",report:"report"},s=t.hidden??{},r=e.filter(a=>!a.quiet&&!a.acked&&!(a.key!==void 0&&s[a.key]===a.stateHash)).map(a=>{let l=n[a.kind??""]??"",u=a.key!==void 0?{hideKey:a.key,hideHash:a.stateHash??""}:{};return a.kind==="decision"&&a.key?{key:"decision:"+a.key,text:a.note||a.verb,label:l,hash:At(a.key),...u}:(a.kind??"question")==="question"&&a.key?{key:"question:"+a.key,text:a.note||a.verb,label:l,hash:At(a.key),...u}:a.kind==="report"&&a.key?{key:"report:"+a.key,text:a.note||a.verb,label:l,href:G(a.key),...u}:typeof a.kind=="string"&&(a.kind.startsWith("pr:")||a.kind==="stack-ready")&&a.prUrl?{key:a.kind+":"+(a.key??a.prUrl),text:a.note||a.kind,href:a.prUrl,label:l,...u}:{key:(a.kind??"question")+":"+(a.key??a.lane+":"+a.id),text:a.note||a.verb,label:l,...a.kind==="watch"?{}:{open:{type:"dispatch",key:a.lane+":"+a.id}},...u}});!r.length&&t.preview&&(r=[{key:"preview",text:"attention questions crawl in here",...t.previewHelm?{open:{type:"helm",key:t.previewHelm}}:{}}]);let o=r.length>4?r.length-4:0;return r=r.slice(0,4),o&&(r[3]={...r[3],text:"\\u2026and "+o+" more \\u2014 see attention",label:""}),r}var vr="data:image/png;base64,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";var kr="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAA2UlEQVR4nGNgwAPeHo35D8K45JnwaRQS/YXPbAacmkEa/3z/BaZx2c6Ey1YGIgAjLsV8PF/g7E9feMC0sPUSRhTNuPwGcjI28AlqENzZIIUw/O41G8O58z/BkiycbGDFl278R3GRENQyJpBTkE1DtgFkyIMnn+EGwQDIApA+uB9AzgeZCtIEMhlmu54GI1gMFgafvvDA/Y4SADADYABkG7LfPyFpxIgq9IBD1ojsbAZ0zYTiFlvoY00ksFAGYWw2wtWhC4BD/gsiQUBcxAbxEiI4MAE+p2PLYQAGj4EmRoa2cwAAAABJRU5ErkJggg==";var vt=()=>i`<span class="pet-art" aria-hidden="true"><div class="sprite" style=${{backgroundImage:`url(${vr})`}}></div><img class="star" src=${kr} alt="" /></span>`;function Qo(e,t){let n="animation-duration:"+((innerWidth+180)/(100+t*12)).toFixed(1)+"s;animation-delay:-"+t*9%14+"s",s=()=>{e.hideKey&&ws(e.hideKey,e.hideHash??"")},r=[i`<div class="bub">${e.label&&[i`<span class="badge dim">${e.label}</span>`," "]}<span>${e.text.length>48?e.text.slice(0,47)+"\\u2026":e.text}</span></div>`,i`<${vt} />`],o=e.open;return e.hash?i`<a key=${e.key} class="lob" style=${n} title="open the decision" href=${e.hash} onClick=${s}>${r}</a>`:e.href?i`<a key=${e.key} class="lob" style=${n} title=${e.label==="report"?"open the report":"open the PR"} href=${e.href} target="_blank" rel="noopener" onClick=${s}>${r}</a>`:i`<div\n key=${e.key}\n class="lob"\n style=${n}\n title="click to open"\n onClick=${()=>{s(),o&&O(o.type,o.key)}}\n >\n ${r}\n </div>`}function br({state:e}){let t=e.snapshot,n=$r(t?.attention||[],{lobs:e.prefs.lobs,hidden:e.lobHidden,preview:e.preview,previewHelm:t&&t.helms.length?t.helms[0].grounds:void 0}),s=n.map(r=>r.key).join("|");return Kt(()=>n.map((r,o)=>Qo(r,o)),[s])}function kt({box:e}){if(!e)return null;let t=n=>{n.target===n.currentTarget&&de()};return i`<div id="lightbox" class="lightbox" role="dialog" aria-label=${e.name} onClick=${t}>\n <button type="button" class="lbclose" title="close" onClick=${de}>\xD7</button>\n <img class="lbimg" src=${e.src} alt=${e.name} />\n <a class="lboriginal" href=${e.src} target="_blank" rel="noopener">open original \xB7 ${e.name}</a>\n </div>`}var he=i`<span class="x" onClick=${ce}>\xD7</span>`,yr=(e,t,n)=>i`<span class="seg">${t.map(([s,r])=>i`<button class=${s===n?"on":""} onClick=${()=>e(s)}>${r}</button>`)}</span>`;function Xo(e,t){let n=yr(ys,[["table","table"],["cards","cards"]],t.view),s=yr(_s,[["on","on"],["off","off"]],t.lobs?"on":"off"),r=e.attentionError?e.attentionError:(e.attentionKinds||[]).join(" \\xB7 ");return[he,i`<h3>\u2699 settings <span class="dim" style="font-weight:normal">\xB7 this browser only</span></h3>`,i`<div class="settings"><div class="row"><span class="lbl">view<span class="hint">cards or table (notices stay a table)</span></span>${n}</div><div class="row"><span class="lbl">lobs<span class="hint">crawling lobsters in this page</span></span>${s}</div><div class="row"><span class="lbl">attention<span class="hint">kinds shown \u2014 attentionKinds in config.toml (read-only here)</span></span><span class="dim" style="font-size:11px;text-align:right;max-width:260px">${r}</span></div></div>`]}function Zo(e,t){let n=me(t.numbers,new Map(t.numbers.map((r,o)=>[r,t.titles[o]])),e.number),s=t.nextMergeable?[" \\xB7 ",i`<span class="ok">next mergeable</span>`]:t.blockedBy?" \\xB7 blocked by #"+t.blockedBy:t.nextNumber?" \\xB7 next is #"+t.nextNumber:"";return[n," \\xB7 ",t.position," of ",t.size," \\xB7 floor ",t.floor,s]}var ea=e=>t=>{t.preventDefault(),O("dispatch",e)};function ta(e,t){let n=Zn(e,t),s=n.pr,r=n.stack,o=n.watch,a=pt(s),l=n.chain.length?n.chain.flatMap((c,d)=>[d?" \\u2192 ":"",c.culled?i`<span class="dim">${c.id.slice(0,8)} (culled)</span>`:[i`<a href="#" onClick=${ea(c.modalKey)}>${c.id.slice(0,8)}</a>`," ",i`<span class="dim">${c.verb}</span>`]]):i`<span class="dim">none</span>`,u=o?[i`<div>${o.key} \xB7 owner ${o.owner||"?"} \xB7 ${o.lastCheckedAt?["checked ",v(o.lastCheckedAt)," ago"]:"never checked"}</div>`,o.lastError&&i`<div class="bad">${o.lastError}</div>`,i`<div class="dim" style="font-size:11px;margin-top:4px">cursor</div>`,T(o.cursor)]:i`<div class="dim">no watch \u2014 <code>lobstah watch add ${s.url}</code> registers one</div>`;return[he,i`<h3>${dt(s)} ${s.title||""} <span class=${"badge "+E(s.badge)}>${s.badge.text}</span>${s.draft&&s.badge.text!=="draft"&&[" ",i`<span class="badge pr-draft">draft</span>`]}</h3>`,i`<div class="sub">${s.repo} \xB7 ${s.state} \xB7 observed ${v(s.observedAt)} ago${s.gate&&" \\xB7 gate "+s.gate}</div>`,i`<div class="sec">checks</div><div>${Ae(s)}</div><div class="sec">review</div><div>${a||i`<span class="dim">no review yet</span>`}</div><div class="sec">merge</div><div>${Re(s)}</div>${s.repairWait&&i`<div class="sec">repair waits</div><div>${s.repairWait.heldBy}: ${s.repairWait.reason}${s.repairWait.until?" \\xB7 until "+s.repairWait.until:""}</div>`}<div class="sec">refs</div><div>${s.headRefName||"?"} \u2192 ${s.baseRefName||"?"}</div><div class="sec">stack</div><div>${r?Zo(s,r):i`<span class="dim">not stacked</span>`}</div><div class="sec">dispatch chain</div><div>${l}</div><div class="sec">watch</div>`,u]}function na(e){let t=Date.now()-Date.parse(e.heartbeatAt)>18e5;return[he,i`<h3>\u26F5 ${e.man}</h3><div class="sub">helm of <b>${e.grounds}</b> (${(e.repos||[]).join(", ")})</div><div class="sub">${e.cwd??"?"}${e.host&&" \\xB7 "+e.host}</div><div class="sub">session ${e.sessionId??""} \xB7 signed on ${v(e.signedOnAt)} ago \xB7 heartbeat <span class=${t?"warn":"ok"}>${v(e.heartbeatAt)} ago</span></div>`,i`<${ot} worker=${e} />`,e.sessionId&&[i`<div class="sec">open this session</div>`,Ge(e)],e.transcript&&[i`<div class="sec">transcript</div>`,T(e.transcript)]]}function sa(e){return[i`<div class="sec">report \xB7 ${e.title}</div>`,i`<div class="sub">${on(e)} \xB7 <a href=${G(e.key)} target="_blank" rel="noopener">open the report \u2197</a></div>`]}function ra(e,t,n){let s=e.claimedBy&&e.claimedBy.startsWith("wt:")?[i`<div class="sec">worked by trap</div>`,i`<div class="claimedby">claimed by ${lt(e.claimedBy.slice(3))}</div>`,T(U(e.claimedBy)),i`<div class="dim" style="font-size:11px">an opted-in interactive session mans this seat \u2014 attach would resume someone\'s live thread. Message it instead: lobstah send ${U(e.claimedBy)} "\u2026"</div>`]:[i`<div class="sec">open this session</div>`,T("lobstah attach "+e.id)];return[he,i`<h3>${e.id.slice(0,8)} <span class=${"badge v-"+e.verb}>${e.verb}</span></h3>`,i`<div class="sub">${e.repo} \xB7 ${e.lane} ${e.bucket} \xB7 ${v(e.verbAt)}${e.for&&[" \\xB7 ",Te(e)]} ${fe(e)}</div>`,s,e.worker&&i`<${ot} worker=${e.worker} headless=${!e.claimedBy?.startsWith("wt:")} />`,e.worktree&&[i`<div class="sec">worktree${e.worktreeOf?" (reused from "+e.worktreeOf.slice(0,8)+")":""}</div>`,T(e.worktree),e.worktreeKept&&i`<div class="dim" style="font-size:11px">kept: ${e.worktreeKept}</div>`],e.transcript&&[i`<div class="sec">transcript</div>`,T(e.transcript)],t&&sa(t),qs(e,n)]}function oa(e){let t=Me(e),n=e.requested?[e.repo??""," \\xB7 ",e.harness??""," \\xB7 requested ",v(e.requested.at)," ago from the glass; the helm starts it with man throw --new."]:e.starting?e.starting.failedAt?[e.repo??""," \\xB7 reserved ",v(e.starting.reservedAt)," ago \\xB7 start failed: ",e.starting.reason??"",". Its addressed work stays queued; a session can still redeem the ticket, or `lobstah stow --wt ",e.name??e.trapId,"` withdraws it."]:[e.repo??""," \\xB7 reserved ",v(e.starting.reservedAt)," ago \\xB7 starting: waiting for a session to redeem the ticket (due by ",e.starting.deadline,")"]:e.live?[e.repo??"addressed bait only"," \\xB7 session ",e.sessionId??""," \\xB7 signed on ",v(e.signedOnAt)," ago \\xB7 ",t.listen," \\xB7 heartbeat ",t.hb]:"signed off \\u2014 registration gone; the lifecycle, messages, and catches are the surviving record. Re-soaking the same worktree restores this address.",s=e.notices.length?e.notices.map(a=>i`<div key=${a.seq} class="loglines">${v(a.at)} ago \xB7 <b>${a.kind}</b> \u2014 ${a.text}</div>`):i`<div class="empty">none recorded</div>`,r=e.messages.length?e.messages.map(a=>i`<div key=${a.file} class=${"msg"+(a.from==="helm"?" from-helm":"")}><div class="hdr">from ${a.from} \xB7 ${a.at&&[v(a.at)," ago"]} \xB7 ${a.state==="pending"?i`<span class="warn">pending</span>`:i`<span class="ok">delivered</span>`}</div>${a.text}${a.attachments?.length?pe(a.attachments,l=>Bn(e.trapId,l)):""}</div>`):i`<div class="empty">none</div>`,o=e.catches.length?e.catches.map(a=>i`<div key=${a.lane+":"+a.id} class="catch click" onClick=${S("dispatch",a.lane+":"+a.id)}><div class="hdr"><b>${a.id.slice(0,8)}</b><span class=${"badge v-"+a.verb}>${a.verb}</span><span class="dim">${v(a.verbAt)}</span>${fe(a)}</div>${a.note&&i`<div class="loglines">${R(a.note)}</div>`}</div>`):i`<div class="empty">none yet</div>`;return[he,i`<h3>\u{1FAA4} ${e.label??`wt:${e.trapId}`} <span class="badge">${e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.live?"live":"signed off"}</span></h3>`,i`<${ot} worker=${e} />`,e.worktree&&i`<div class="sub">${e.worktree}</div>`,i`<div class="sub">${n}</div>`,i`<div class="sec">window</div>`,Y(e),Q(e),e.live&&!(e.link&&ne(e))&&e.sessionId&&[i`<div class="sec">open this session</div>`,Ge(e),i`<div class="dim" style="font-size:11px">as registered at sign-on \u2014 a hookless enlistment may hold a made-up id</div>`],i`<div class="sec">lifecycle (${e.notices.length})</div>`,s,i`<div class="sec">messages (${e.messages.length})</div>`,r,i`<div class="sec">catches (${e.catches.length})</div>`,o]}function _r({snapshot:e,modal:t,prefs:n,detail:s=null}){if(!e||!t)return null;let r=oe(e,t,s);if(!r&&t.type==="dispatch"&&s?.key===t.key)return[he,i`<h3>${t.key.slice(t.key.indexOf(":")+1,t.key.indexOf(":")+9)}</h3>`,i`<div class=${s.error?"bad":"dim"}>${s.error??"loading\\u2026"}</div>`];if(!r)return null;if(t.type==="settings")return Xo(r,n);if(t.type==="pr")return ta(e,t.key);if(t.type==="helm")return na(r);if(t.type==="dispatch"){let o=Fn(e,r);return ra(r,o,s)}return oa(r)}var aa=e=>i`<tr key=${e.seq}><td class="dim">${v(e.at)}</td><td>${e.kind}</td><td class="grow">${e.text}</td><td class="dim">${e.repo??""}</td></tr>`,wr=({inp:e,more:t})=>[M(["at","kind","text","repo"],e.list.map(aa),"no notices"),t&&i`<${ue} kind="notices" more=${t} />`];function Sr(e){let t=new Map;for(let n of e.prs){let s=t.get(n.stackId)||[];s.push(n),t.set(n.stackId,s)}return e.stacks.map(n=>({s:n,prs:t.get(n.id)||[]})).filter(n=>n.prs.length)}var Dr=(e,t)=>me(e.numbers,new Map(t.map(n=>[n.number,n.title]))),cn=e=>e.state+(e.draft?" \\xB7 draft":"")+(e.state==="MERGED"&&e.mergedAt?" \\xB7 "+e.mergedAt:"");function xr(e){let t=s=>{let r=String(s??"");return r.length>24?r.slice(0,23)+"\\u2026":r},n=e.watches.map(s=>i`<tr key=${s.key}><td>${s.key}</td><td>${s.owner}</td><td title=${s.cursor}>${t(s.cursor)}</td><td>${s.lastCheckedAt&&v(s.lastCheckedAt)}</td><td>${s.lastError||""}</td></tr>`);return[i`<h2>other watches</h2>`,M(["key","owner","cursor","last check","error"],n,"no other watches")]}function ia(e,t){let n=Sr(e).flatMap(({s,prs:r})=>[i`<tr key=${"stack:"+s.id}><th colspan="8">${Dr(s,r)} \xB7 floor ${s.floor}${s.open?" \\xB7 open":" \\xB7 history"}${s.readiness&&i`<div class=${s.readiness.allReady?"ok":"dim"}>${s.readiness.text}</div>`}</th></tr>`,...r.map(o=>i`<tr key=${o.key} class="rowhead" onClick=${S("pr",o.key)}><td>${dt(o)}</td><td class="grow">${o.title||""}</td><td>${cn(o)}</td><td>${Ae(o)}</td><td>${pt(o)}</td><td>${Re(o)}</td><td>${Qt(o.watch)}</td><td>${o.gate||""}</td></tr>`)]);return[M(["PR","title","state","checks","review","merge","watch","gate"],n,"no PR evidence"),t,xr(e)]}function la(e,t){let n=Sr(e),s=o=>i`<div key=${o.key} class="card" onClick=${S("pr",o.key)}><div class="top">${ct(o)}<span class=${"badge "+E(o.badge)+B(o.badge.text)} title=${j(o.badge.text)}>${o.badge.text}</span></div><div class="meta" title=${`${o.repo} \\xB7 ${cn(o)}`}>${o.repo} \xB7 ${cn(o)} \xB7 ${Re(o)}</div><div class="foot"><span>${Ae(o)}</span><span>${Qt(o.watch)}</span>${o.gate&&i`<span>gate ${o.gate}</span>`}</div></div>`;return[n.length?n.map(({s:o,prs:a})=>i`<${ee} key=${"stack:"+o.id}><h2>${Dr(o,a)} \xB7 floor ${o.floor}${o.open?"":" \\xB7 history"}</h2>${o.readiness&&i`<div class=${o.readiness.allReady?"ok":"dim"}>${o.readiness.text}</div>`}<div class="cards">${a.map(s)}</div><//>`):i`<div class="empty">no PR evidence</div>`,t,xr(e)]}function Gr({inp:e,more:t}){let n=t&&i`<${ue} kind="prs" more=${t} />`;return e.view==="cards"?la(e,n):ia(e,n)}var da=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],ca=5,pn=(e,t,n=t+"es")=>`${e} ${e===1?t:n}`,pa=e=>e.count?`${pn(e.count,"catch")} on ${e.date}`:`No catches on ${e.date}`,Cr=new WeakSet,ua=e=>{!e||Cr.has(e)||(Cr.add(e),e.scrollLeft=e.scrollWidth)},Tr={ArrowUp:-1,ArrowDown:1,ArrowLeft:-7,ArrowRight:7};function fa({page:e,focus:t}){let n=e.weeks.flat(),s=t&&n.some(u=>u.date===t)?t:e.today,r=u=>{let c=n.findIndex(p=>p.date===s),d;if(u.key in Tr)d=c+Tr[u.key];else if(u.key==="Home")d=0;else if(u.key==="End")d=n.length-1;else return;u.preventDefault();let h=n[Math.max(0,Math.min(n.length-1,d))];Ht(h.date),u.currentTarget.querySelector(`[data-date="${h.date}"]`)?.focus()},o=e.weeks.length-1,a=(u,c,d)=>{let h=u[d];if(!h)return i`<td key=${c} class="pad"></td>`;let p=pa(h),m=c<4?" tl":c>o-4?" tr":"";return i`<td\n key=${c}\n role="gridcell"\n class=${`day l${h.level}${d<2?" below":""}${m}`}\n data-date=${h.date}\n data-tip=${p}\n aria-label=${p}\n tabindex=${h.date===s?0:-1}\n onFocus=${()=>Ht(h.date)}\n ></td>`},l=e.months[0]?.week??e.weeks.length;return i`<div class="heat-scroll" ref=${ua}>\n <table class="heatmap" role="grid" aria-label=${`Catches per day, last ${e.weeks.length} weeks`} onKeyDown=${r}>\n <thead aria-hidden="true">\n <tr>\n <td class="wd"></td>\n ${l>0&&i`<td colspan=${l}></td>`}\n ${e.months.map((u,c)=>i`<td key=${u.week} class="month" colspan=${(e.months[c+1]?.week??e.weeks.length)-u.week}><span>${u.label}</span></td>`)}\n </tr>\n </thead>\n <tbody>\n ${da.map((u,c)=>i`<tr key=${u} role="row">\n <td class="wd" aria-hidden="true">${c%2?u:""}</td>\n ${e.weeks.map((d,h)=>a(d,h,c))}\n </tr>`)}\n </tbody>\n </table>\n </div>`}var ma=()=>i`<div class="heat-legend" aria-hidden="true">\n Less ${[0,1,2,3,4].map(e=>i`<span key=${e} class=${"swatch l"+e}></span>`)} More\n </div>`;function ha({page:e}){let t=[["today",e.catchesToday],["this week",e.catchesThisWeek],["total",e.totalCatches]];return i`<div class="stat-tiles">\n ${t.map(([n,s])=>i`<div key=${n} class="stat-tile"><div class="n">${s}</div><div class="dim">${n}</div></div>`)}\n </div>`}function ga({page:e}){let t=e.perTrap.slice(0,ca);if(!t.length)return null;let n=t[0].catches||1;return i`<section class="top-traps">\n <h2>Top traps <span class="dim">\xB7 all time</span></h2>\n <ol>\n ${t.map(s=>i`<li key=${s.name}><span class="name" title=${s.name}>${s.name}</span><span class="bar"><span style=${{width:`${s.catches/n*100}%`}}></span></span><span class="n">${pn(s.catches,"catch")}</span></li>`)}\n </ol>\n </section>`}function Ar({page:e,error:t,focus:n}){return e?i`<div class="stats">\n <${ha} page=${e} />\n ${e.totalCatches===0&&i`<div class="stats-empty"><${vt} /><div><b>No catches yet.</b> <span class="dim">A dispatch that finishes done is a catch; each one lands on its day here.</span></div></div>`}\n <section class="heat">\n <h2>Catches per day</h2>\n <${fa} page=${e} focus=${n} />\n <div class="heat-foot">\n <span class="dim"\n >${e.undated>0?`${pn(e.undated,"earlier catch")} ${e.undated===1?"has":"have"} no recorded day${e.historyFrom?`; daily history starts ${e.historyFrom}`:""}.`:""}</span\n >\n <${ma} />\n </div>\n </section>\n <${ga} page=${e} />\n ${t&&i`<div class="dim">${t}; showing the last numbers read.</div>`}\n </div>`:i`<div class="empty">${t??"loading stats\\u2026"}</div>`}var un=e=>e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??(e.live?"":"signed off"),Rr=e=>e.live||e.starting?"":" dim";function $a(e){let t=Me(e);return i`<tr key=${e.trapId} class=${"rowhead"+Rr(e)} onClick=${S("trap",e.trapId)}><td><b>${e.label??`wt:${e.trapId}`}</b></td><td>${e.repo??"\\u2014"}</td><td class="grow">${e.worktree??""}</td><td>${e.harness&&i`<${H} worker=${e} cls="" />`}</td><td>${(e.sessionId??"").slice(0,8)}</td><td>${Pe(e)}${Q(e)}</td><td>${t.listen}</td><td>${t.hb}</td><td>${Zt(e)}</td><td class="catchn" title="catches">\u{1F99E} ${te(e.totalCatches??0)}</td><td>${Y(e)}</td></tr>`}function va(e){let t=Me(e),n=Zt(e),s=`${e.repo??(e.live?"addressed bait only":"history")}${e.sessionId?" \\xB7 session "+e.sessionId.slice(0,8):""}`;return i`<div key=${e.trapId} class=${"card"+Rr(e)} onClick=${S("trap",e.trapId)}><div class="top"><b>\u{1FAA4} ${e.label??`wt:${e.trapId}`}</b>${!e.requested&&!e.starting&&e.harness?i`<${H} worker=${e} />`:i`<span class=${"badge"+B(un(e))} title=${j(un(e))}>${un(e)}</span>`}</div><div class="meta" title=${s}>${s}</div>${e.worktree&&i`<div class="note" title=${e.worktree}>${e.worktree}</div>`}<div class="note" title=${ft(e)}>${Pe(e)}</div>${Q(e)}<div class="foot"><span>${t.listen}${e.live&&[" \\xB7 heartbeat ",t.hb]} \xB7 <span class="catchn" title="catches">\u{1F99E} ${te(e.totalCatches??0)}</span>${n&&[" \\xB7 ",n]}</span><span class="footact">${Y(e)}</span></div></div>`}function Mr({inp:e}){let t=e.list.map(s=>s.x),n=i`<div class="tabhead"><${ut} /></div>`;return e.view==="cards"?[n,t.length?i`<div class="cards">${t.map(va)}</div>`:i`<div class="empty">no traps soaking</div>`]:[n,M(["address","repo","worktree","harness","session","now","listening","heartbeat","mail","catches","window"],t.map($a),"no traps soaking")]}function Pr({state:e}){let t=ae(e),n=e.route,s=t?et():[],r=t&&Xn(t,{st:e.prefs,modal:e.modal,detail:e.detail},Date.now()),o=u=>({left:e.snapshot?Yn(e.snapshot,e.older,u):0,loading:e.olderLoading===u,error:e.olderError?.kind===u?e.olderError.text:void 0}),a=u=>!r||u!==n?null:u==="deck"?i`<${ur} inp=${r.deck} drafts=${e.drafts} focus=${e.focusDecision} viewedHere=${e.viewedHere} unread=${s.length} />`:u==="dispatches"?i`<${fr} inp=${r.dispatches} more=${o("dispatches")} />`:u==="traps"?i`<${Mr} inp=${r.traps} />`:u==="prs"?i`<${Gr} inp=${r.prs} more=${o("prs")} />`:u==="reports"?i`<${Ys} inp=${r.reports} />`:u==="stats"?i`<${Ar} page=${e.stats} error=${e.statsError} focus=${e.statsFocus} />`:i`<${wr} inp=${r.notices} more=${o("notices")} />`,l=u=>{u.target===u.currentTarget&&ce()};return[i`<${hr} d=${t} inp=${r} tab=${n} st=${e.prefs} stale=${e.stale} unread=${s.length} />`,se.map(u=>i`<main key=${u} id=${"page-"+u} class=${t&&u===n?"tabpage on":"tabpage"}><div id=${u}>${a(u)}</div></main>`),i`<footer id="foot"><${gr} d=${t} /></footer>`,i`<div id="lobs"><${br} state=${e} /></div>`,i`<${kt} box=${e.lightbox} />`,i`<div id="overlay" class=${e.modal&&t?"open":t?"":void 0} onClick=${l}><div class="modal" id="modalbox"><${_r} snapshot=${t} modal=${e.modal} prefs=${e.prefs} detail=${e.detail} /></div></div>`,t&&i`<${dr} open=${e.decisionModal} order=${_e()} drafts=${e.drafts} extensions=${t.answerLimits?.extensions??[]} />`,t&&i`<${cr} unread=${s} dismissed=${e.alertDismissed} />`]}function ka({view:e}){if(e.state==="loading")return i`<main class="reportview"><div class="dim">loading\u2026</div></main>`;if(e.state==="error")return i`<main class="reportview"><div class="bad">${e.error}</div></main>`;let t=e.report;return i`<main class="reportview">\n <h1>${t.title}</h1>\n <${ar} r=${t} text=${e.text!==void 0?{text:e.text}:{error:e.error}} />\n </main>`}function Ir({view:e,box:t}){return[i`<${ka} view=${e} />`,i`<${kt} box=${t} />`]}async function Er(e){let t=encodeURIComponent(e),n,s;try{let r=await fetch(`/report/${t}/meta`);if(!r.ok)return{state:"error",error:`report not found (${r.status})`};s=r.headers?.get("x-lobstah-token")??void 0,n=JSON.parse(await r.text())}catch{return{state:"error",error:"report could not be read"}}try{let r=await fetch(Vn(e)),o=r.ok?{text:await r.text()}:{error:`report not found (${r.status})`};return{state:"ready",report:n,...o,...s?{token:s}:{}}}catch{return{state:"ready",report:n,error:"report could not be read"}}}async function Or(e){if(!(e.state!=="ready"||e.text===void 0||e.report.acked||!e.token))try{await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":e.token},body:JSON.stringify({kind:"report-viewed",payload:{key:e.report.key}})})}catch{}}var ba=3e4,Lr="lobstah-glass-page",Hr="lobstah-glass-shown",ya=20;function _a(){try{let t=sessionStorage.getItem(Lr);if(t&&/^[A-Za-z0-9_-]{8,64}$/.test(t))return t}catch{}let e="";try{e=Array.from(crypto.getRandomValues(new Uint8Array(12)),t=>t.toString(16).padStart(2,"0")).join("")}catch{for(;e.length<24;)e+=Math.random().toString(36).slice(2);e=e.slice(0,24)}try{sessionStorage.setItem(Lr,e)}catch{}return e}var Nr=null,jr=()=>Nr??(Nr=_a()),mn=[];function Br(){try{let e=JSON.parse(sessionStorage.getItem(Hr)??"[]");if(Array.isArray(e))return e.filter(t=>typeof t=="string")}catch{}return mn}function wa(e){mn=[...Br(),e].slice(-ya);try{sessionStorage.setItem(Hr,JSON.stringify(mn))}catch{}}function Sa(e){if(!e||typeof e!="object")return!1;let{id:t,hash:n}=e;if(typeof t!="string"||!t||!qn(n)||Br().includes(t))return!1;if(wa(t),n==="")return!0;let s=be(n);return s!==null?location.pathname!==G(s)&&location.assign(G(s)):location.pathname!=="/"?location.assign(`/${n}`):location.hash!==n&&(location.hash=n),!0}var fn=!1;async function Oe(){if(!fn){fn=!0;try{let e=document.hidden?"hidden":"visible",t=await fetch(`/api/presence?page=${jr()}&vis=${e}`,{method:"POST",cache:"no-store"});if(!t.ok)return;Sa((await t.json())?.show)}catch{}finally{fn=!1}}}function hn(e){let t=null,n=0,s=()=>{let r=document.hidden?ba:e??0;r!==n&&(t&&clearInterval(t),t=r?setInterval(()=>{Oe()},r):null,n=r)};document.addEventListener("visibilitychange",()=>{s(),Oe()}),window.addEventListener("pagehide",()=>{try{navigator.sendBeacon?.(`/api/presence?page=${jr()}&vis=gone`)}catch{}}),s(),Oe()}var gn=!1,Le=null,Ne=null;function Da(e){let t=e.headers?.get("x-lobstah-beats");if(t)try{return JSON.parse(decodeURIComponent(t))}catch{return}}async function $n(){if(!gn){gn=!0,Oe();try{let e=await fetch("/data",{cache:"no-store",headers:Ne?{"if-none-match":Ne}:{}});if(e.status===304){let t=Da(e);t?ps(t):Xe(await xa())}else{if(!e.ok)throw new Error(`/data answered ${e.status}`);Ne=e.headers?.get("etag")??null,Xe(await e.json())}Nt(),g().route==="stats"&&De()}catch{$s()}finally{gn=!1}}}async function xa(){Ne=null;let e=await fetch("/data",{cache:"no-store"});if(!e.ok)throw new Error(`/data answered ${e.status}`);return Ne=e.headers?.get("etag")??null,await e.json()}var Ur=()=>{Le||(Le=setInterval($n,2e3))},Ga=()=>{Le&&clearInterval(Le),Le=null};function Wr(){document.addEventListener("visibilitychange",()=>{document.hidden?Ga():($n(),Ur())}),$n(),document.hidden||Ur()}var vn=()=>jn(location.hash),Fr=e=>window.addEventListener("hashchange",()=>e(vn()));function Kr(){let e=be(location.hash);return e===null?!1:(location.replace(G(e)),!0)}var Vr=()=>({snapshot:void 0,route:vn(),prefs:ns(),modal:null,detail:null,older:It,olderLoading:null,olderError:null,stale:!1,lobHidden:rs(),focusResults:{},preview:new URLSearchParams(location.search).has("lob"),drafts:{},focusDecision:re(location.hash),decisionModal:re(location.hash)?{key:re(location.hash)}:null,viewedHere:{},alertDismissed:[],lightbox:null,stats:null,statsError:null,statsFocus:null}),qr=Kn(location.pathname);qr!==null?Ca(qr):Kr()||Ta();function Ca(e){Et(Vr());let t={state:"loading"},n=()=>Ct(Z(Ir,{view:t,box:g().lightbox}),document.body);document.title="report \\xB7 lobstah glass",Ot(n),n(),hn(2e3),Er(e).then(s=>{t=s,s.state==="ready"&&(document.title=`${s.report.title} \\xB7 lobstah glass`),n(),Or(s)}),document.addEventListener("keydown",s=>{s.key==="Escape"&&g().lightbox&&de()})}function Ta(){Et(Vr());let e,t=!1,n=()=>{let a=g(),l=a.route!==e||!t&&!!a.snapshot;Ct(Z(Pr,{state:a}),document.body),e=a.route,t||(t=!!a.snapshot),l&&window.scrollTo(0,0),a.focusDecision||(s=null),r(a.focusDecision)},s=null;function r(a){if(!a||a===s)return;let l=[...document.querySelectorAll("[data-decision]")].find(u=>u.getAttribute("data-decision")===a);l&&(s=a,l.scrollIntoView?.({block:"center"}))}Ot(n),n(),Fr(a=>{if(Kr())return;let l=re(location.hash);l!==g().focusDecision&&(s=null),k({route:a,focusDecision:l}),l&&ie(l),a==="stats"&&De()});let o=a=>!!a&&(!!a.closest?.("input, textarea, select, [contenteditable]")||a.isContentEditable===!0);document.addEventListener("keydown",a=>{let l=g(),u=a.target;if(a.key==="Escape"){l.lightbox?de():l.decisionModal?o(u)&&u.closest?.(".dmodal")?(u.blur(),document.querySelector(".dmodal")?.focus()):le():ce();return}if(!(a.metaKey||a.ctrlKey||a.altKey||a.isComposing||a.keyCode===229||o(u)||l.lightbox)){if(l.decisionModal){a.key==="ArrowLeft"||a.key==="ArrowRight"?(a.preventDefault(),we(a.key==="ArrowLeft"?-1:1)):/^[1-9]$/.test(a.key)?ls(Number(a.key))&&a.preventDefault():a.key==="Enter"&&u?.matches?.(".dmodal .dopt.on")&&l.decisionModal.key&&(a.preventDefault(),tt(l.decisionModal.key));return}a.key==="d"&&!a.shiftKey&&!l.modal&&(a.preventDefault(),ie())}}),hn(),Wr(),g().route==="stats"&&De()}})();</script>\n </body>\n</html>\n';
17405
+ var GLASS_PAGE = '<!doctype html>\n<html>\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width,initial-scale=1" />\n <title>spyglass</title>\n <link rel="icon" type="image/png" href="/icon.png" />\n <style>:root{--bg: #0e1116;--card: #161b22;--line: #2b3240;--line-hover: #3a455a;--row-hover: #1c2330;--inset: #10151c;--seg-on: #26436b;--scrim: rgba(4, 7, 11, 0.72);--fg: #dbe2ea;--dim: #8b96a5;--ok: #4fc17c;--warn: #e2b93d;--bad: #e26d5c;--link: #6cb2e2;--on-fill: #fff;--pr-merged: #8957e5;--pr-merged-fg: #ab7df8;--pr-open: #238636;--pr-draft: #6e7681;--pr-closed: #da3633;--lobstah: #eb6644;--heat-0: var(--inset);--heat-1: color-mix(in srgb, var(--lobstah) 30%, var(--card));--heat-2: color-mix(in srgb, var(--lobstah) 55%, var(--card));--heat-3: color-mix(in srgb, var(--lobstah) 78%, var(--card));--heat-4: var(--lobstah);--heat-cell: 11px;--heat-gap: 3px;--font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;--font-size: 13px;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--page-pad-block: 14px;--radius: 6px;--card-radius: 8px;--card-pad: 12px 14px;--card-min: 300px;--deck-card-min: 240px;--badge-radius: 5px;--badge-pad: 1px 7px;--badge-font: 11px;--modal-radius: 10px;--modal-width: 780px;--layer-modal: 10;--layer-decision-modal: 15;--layer-alert: calc(var(--layer-modal) - 1);--unread-bg: color-mix(in srgb, var(--bad) 16%, var(--card))}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:var(--font-size)/1.45 var(--font-mono);padding-block:var(--page-pad-block);padding-inline:var(--space-4);display:flex;flex-direction:column;min-height:100vh}h1{font-size:15px;margin:0 0 10px}h1 .dim{color:var(--dim);font-weight:normal}h2{font-size:12px;color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;margin:20px 0 6px}.chips,.controls{display:flex;gap:var(--space-2);flex-wrap:wrap;align-items:center}.controls{margin:0 0 14px}.chips{margin-bottom:8px}.chip{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:3px 9px}.controls select,.newtrap select,.controls input[type=search]{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);color:var(--fg);font:inherit;padding:4px 8px}.controls input[type=search]{flex:1 1 140px;min-width:120px;max-width:340px}#chain-control{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}#f-chain{margin:0;width:14px;height:14px;accent-color:var(--link)}.tabs{display:flex;gap:var(--space-1);border-bottom:1px solid var(--line);margin:8px 0 10px}.tabs a{color:var(--dim);padding:6px 11px;border-bottom:2px solid transparent}.tabs a.on{color:var(--fg);border-color:var(--link)}.tabpage{display:none}.tabpage.on{display:block;flex:1 0 auto}.headerline{display:flex;align-items:center;gap:var(--space-2)}.headerline h1{flex:1}#settings-slot{min-width:34px;text-align:right;color:var(--dim)}#settings-slot #gearbtn{margin-left:0}.deckgrid{display:flex;flex-direction:column;gap:var(--space-3)}.deckgrid h2{margin:5px 0}.deckgrid section{width:100%;min-width:0}.deckline{padding:2px 0;border-top:1px solid var(--line);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.deckline{display:flex;gap:0.35em}a.deckline>b{min-width:0;overflow:hidden;text-overflow:ellipsis}a.deckline>.dim{flex-shrink:0}.deckline.acked,.card.acked,.rowhead.acked,.badge.acked{opacity:0.55}.deckmore{color:var(--dim);font-size:11px;display:inline-block;margin-top:4px}.deckline.click{cursor:pointer}.deckline.click:hover{background:var(--row-hover)}.deckgrid h2 a{color:inherit}.deckgrid h2 a:hover{color:var(--fg)}.deckgrid .cards{grid-template-columns:repeat(auto-fill,minmax(min(var(--deck-card-min),100%),1fr));gap:10px}.deckstack{margin-bottom:9px}.deckstack>.dim{font-size:11px;margin:3px 0 5px}.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.seg button{background:var(--card);border:none;color:var(--dim);font:inherit;padding:4px 11px;cursor:pointer}.seg button.on{background:var(--seg-on);color:var(--fg)}.wrap{overflow-x:auto}table{border-collapse:collapse;width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}th,td{text-align:left;padding:4px 9px;border-top:1px solid var(--line);vertical-align:top;white-space:nowrap}td.grow{white-space:normal;word-break:break-word;min-width:140px}th{color:var(--dim);font-weight:normal;border-top:none;font-size:11px}tr.rowhead{cursor:pointer}tr.rowhead:hover{background:var(--row-hover)}.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--card-min),100%),1fr));gap:var(--space-3)}.card{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad);cursor:pointer;min-width:0;overflow:hidden;overflow-wrap:anywhere}.card:hover{border-color:var(--line-hover)}.worker-harness{cursor:help}.worker-harness:focus-visible{outline:2px solid var(--ok);outline-offset:3px}.worker-tooltip{position:fixed;z-index:20;max-width:264px;padding:6px 9px;background:var(--card);color:var(--fg);border:1px solid var(--line-hover);border-radius:var(--badge-radius);box-shadow:0 3px 12px var(--scrim);font-size:12px;white-space:normal;pointer-events:none}.worker-details dl{display:grid;grid-template-columns:max-content 1fr;gap:4px 14px;font-size:12px}.worker-details dt{color:var(--dim)}.worker-details dd{margin:0;overflow-wrap:anywhere}.card .top{display:flex;justify-content:space-between;gap:var(--space-3);align-items:center;min-height:22px}.card .top>b,.card .top>.prname{flex:1 1000000 auto;min-width:min(10ch,100%);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card .top .badge{flex:0 0 auto}.card .top .badge.long{flex:0 1 auto;min-width:min(12ch,100%);max-width:min(26ch,100%);overflow:hidden;text-overflow:ellipsis}.card .meta{color:var(--dim);font-size:12px;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.card .note{margin-top:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.activity{margin-top:4px;font-size:12px;color:var(--fg);opacity:0.85}.waiting{margin-top:4px;font-size:12px;color:var(--dim)}.activity.stale{color:var(--dim);opacity:1}.card .foot{margin-top:8px;display:flex;gap:10px;flex-wrap:wrap;align-items:center;color:var(--dim);font-size:12px}.card .foot>*{min-width:0}.card .foot .footact{margin-left:auto}.catchn{white-space:nowrap}.btn{background:var(--card);border:1px solid var(--line);border-radius:5px;color:var(--dim);font:inherit;font-size:11px;padding:1px 8px;cursor:pointer;white-space:nowrap}.btn:hover{color:var(--fg);border-color:var(--line-hover)}.badge{border-radius:var(--badge-radius);padding:var(--badge-pad);font-size:var(--badge-font);line-height:1.5;border:1px solid var(--line);white-space:nowrap;display:inline-block}.badge.pr-merged{background:var(--pr-merged);border-color:var(--pr-merged-fg);color:var(--on-fill)}.badge.pr-open{background:var(--pr-open);border-color:var(--pr-open);color:var(--on-fill)}.badge.pr-draft{background:var(--pr-draft);border-color:var(--pr-draft);color:var(--on-fill)}.badge.pr-closed{background:var(--pr-closed);border-color:var(--pr-closed);color:var(--on-fill)}.badge.pr-conflicts{background:var(--pr-closed);border-color:var(--pr-closed);color:var(--on-fill)}.badge.pr-behind{background:var(--pr-draft);border-color:var(--pr-draft);color:var(--on-fill)}.badge.unreported{font-weight:normal;font-size:10px;padding:0 5px;vertical-align:1px}.v-done{color:var(--ok)}.v-working,.v-queued{color:var(--fg)}.v-needs-decision,.v-blocked{color:var(--bad);font-weight:bold}.v-failed{color:var(--bad)}.v-paused,.v-unknown{color:var(--dim)}.dim{color:var(--dim)}.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}.detail{display:none}.detail.open{display:table-row}.detail td{background:var(--inset);white-space:pre-wrap;word-break:break-word;font-size:12px;color:var(--dim)}.detail b{color:var(--fg)}.empty{color:var(--dim);padding:6px 2px}.older{padding:8px 2px}#stale{display:none;color:var(--bad)}a{color:var(--link);text-decoration:none}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:middle}.dot.ok{background:var(--ok)}.dot.warn{background:var(--warn)}.dot.bad{background:var(--bad)}.dot.dim{background:var(--dim)}#overlay{position:fixed;inset:0;background:var(--scrim);display:none;z-index:var(--layer-modal);padding:28px 16px;overflow:auto}#overlay.open{display:block}.modal{max-width:var(--modal-width);margin:0 auto;background:var(--card);border:1px solid var(--line);border-radius:var(--modal-radius);padding:16px 18px;position:relative}.modal .x{position:absolute;top:8px;right:12px;cursor:pointer;color:var(--dim);font-size:18px;line-height:1}.modal .x:hover{color:var(--fg)}.modal h3{margin:0 24px 2px 0;font-size:14px}.modal .sub{color:var(--dim);font-size:12px;margin-bottom:10px}.modal .sec{color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;font-size:11px;margin:14px 0 4px}.modal pre{white-space:pre-wrap;word-break:break-word;margin:0;font:inherit;color:var(--fg)}.msg{border-left:3px solid var(--line);padding:3px 10px;margin:8px 0;white-space:pre-wrap;word-break:break-word}.msg.from-helm{border-color:var(--link)}.msg .hdr{color:var(--dim);font-size:11px}.catch{border:1px solid var(--line);border-radius:var(--radius);padding:6px 10px;margin:8px 0}.catch.click{cursor:pointer}.catch .hdr{display:flex;gap:10px;flex-wrap:wrap;align-items:baseline}.loglines{color:var(--dim);font-size:12px;white-space:pre-wrap;word-break:break-word;margin-top:4px}.cmd{display:flex;gap:var(--space-2);align-items:center;margin:5px 0;flex-wrap:wrap}.cmd code{background:var(--inset);border:1px solid var(--line);border-radius:5px;padding:3px 8px;word-break:break-all;cursor:pointer}.cmd.inline{display:inline-flex;margin:0}.cmd code:hover{border-color:var(--line-hover)}.cmd code.copied{border-color:var(--ok)}.cmd button{background:var(--card);border:1px solid var(--line);border-radius:5px;color:var(--dim);font:inherit;font-size:11px;padding:2px 8px;cursor:pointer}.cmd button:hover{color:var(--fg)}.chip.click{cursor:pointer}.chip.click:hover{border-color:var(--line-hover)}footer{margin-top:26px;padding-top:10px;border-top:1px solid var(--line);color:var(--dim);font-size:12px;display:flex;gap:var(--space-2);flex-wrap:wrap}.lob{position:fixed;bottom:6px;left:0;z-index:5;cursor:pointer;font-size:34px;line-height:1;user-select:none;animation:crawl 18s linear infinite}a.lob{color:inherit}.lob .bub .badge{display:inline-block;margin:0 0 3px}.pet-art{display:block;position:relative;width:72px;height:56px}.pet-art .sprite{width:72px;height:56px;background-position:0 0;background-repeat:no-repeat;background-size:400% 100%;image-rendering:pixelated;animation:step 0.5s steps(4) infinite}.lob .bub{display:none;position:absolute;bottom:58px;right:-8px;z-index:2;background:var(--card);border:1px solid var(--line);border-radius:9px;padding:6px 9px 5px;font-size:11px;line-height:1.35;color:var(--fg);width:max-content;max-width:150px;box-shadow:0 2px 8px rgba(0,0,0,0.4)}.lob:hover .bub{display:block}.lob .bub span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:normal;word-break:break-word}.pet-art .star{position:absolute;left:56px;top:-9px;height:14px;image-rendering:pixelated;z-index:3}.lob:hover{animation-play-state:paused}@keyframes crawl{0%{transform:translateX(-90px)}100%{transform:translateX(100vw)}}@keyframes step{to{background-position-x:-288px}}#gearbtn{background:none;border:1px solid var(--line);border-radius:var(--radius);color:var(--dim);font:inherit;font-size:13px;padding:1px 7px;margin-left:8px;cursor:pointer;vertical-align:1px}#gearbtn:hover,#gearbtn.on{color:var(--fg);border-color:var(--line-hover)}.settings .row{display:flex;justify-content:space-between;align-items:center;gap:14px;margin:12px 0}.settings .lbl{color:var(--fg);font-size:12px}.settings .hint{display:block;color:var(--dim);font-size:11px;margin-top:2px}.dlist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.drow{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2);background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:8px 12px}.drow.unread{background:var(--unread-bg);border-color:var(--bad)}.drow.answered{opacity:0.7}.drow.focus{animation:dflash 1.6s ease-out 1}.drow .dopen{flex:1 1 280px;display:flex;align-items:baseline;gap:var(--space-2);min-width:0;background:none;border:none;padding:0;color:var(--fg);font:inherit;text-align:left;cursor:pointer}.drow .dopen:hover .dtitle{text-decoration:underline}.drow .dtitle{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drow .dmeta,.drow .dage{font-size:11px}.drow .dlink,.dmodal .dlink{color:var(--link)}.dstate{font-size:var(--badge-font);border-radius:var(--badge-radius);padding:var(--badge-pad);border:1px solid var(--line);color:var(--dim)}.dstate.unread{border-color:var(--bad);color:var(--bad)}.dstate.answered{color:var(--ok)}.dbadge{display:inline-block;margin-left:6px;min-width:1.6em;text-align:center;border-radius:999px;padding:0 6px;font-size:11px;font-weight:bold;background:var(--bad);color:var(--on-fill)}#doverlay{position:fixed;inset:0;background:var(--scrim);z-index:var(--layer-decision-modal);padding:28px 16px;overflow:auto}.dmodal:focus{outline:none}.dmodal .x{background:none;border:none;font:inherit;font-size:18px;color:var(--dim)}.dnav{display:flex;align-items:center;gap:var(--space-2);margin:0 28px var(--space-3) 0}.dnav .dpos{color:var(--dim);font-size:11px}.dmodal .dtop{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2);margin-bottom:var(--space-2)}.dmodal .dtitle{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px}.dmodal .dmeta{font-size:11px}.ddone{padding:28px 8px;text-align:center;cursor:pointer}.ddone .ok{font-size:15px;margin-bottom:var(--space-2)}.dalert-live{position:fixed;right:var(--space-4);bottom:var(--space-4);z-index:var(--layer-alert)}.dalert{display:flex;align-items:center;gap:4px;background:var(--card);border:1px solid var(--bad);border-radius:var(--card-radius);padding:8px 10px;box-shadow:0 6px 24px var(--scrim)}.dalert .dalert-open{display:flex;align-items:center;gap:var(--space-2);background:none;border:none;color:var(--fg);font:inherit;cursor:pointer}.dalert .dx{background:none;border:none;color:var(--dim);font:inherit;font-size:15px;cursor:pointer}.dcount{display:inline-block;min-width:1.8em;text-align:center;border-radius:999px;padding:1px 7px;font-weight:bold;background:var(--bad);color:var(--on-fill);animation:dglow 1.8s ease-in-out infinite}@keyframes dglow{0%,100%{box-shadow:0 0 0 0 transparent}50%{box-shadow:0 0 10px 3px var(--bad)}}@media(prefers-reduced-motion:reduce){.dcount,.drow.focus{animation:none}}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@keyframes dflash{0%,35%{border-color:var(--link);box-shadow:0 0 0 3px var(--link)}100%{border-color:var(--line);box-shadow:0 0 0 0 transparent}}.dfiles{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:6px 0}.dfiles .dimg img{max-height:160px;max-width:320px;border:1px solid var(--line);border-radius:var(--radius);display:block}.dfiles .dfile{width:100%;font-size:11px}.doptions{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 6px}.btn.dopt{font-size:12px;padding:3px 12px;color:var(--fg)}.btn.dopt.on{background:var(--seg-on);border-color:var(--link)}.danswer{display:block;width:100%;min-height:3.2em;max-height:50vh;margin:6px 0;padding:6px 8px;resize:vertical;overflow-y:auto;field-sizing:content;background:var(--inset);color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);font:inherit}.dkey,.dlegend kbd{display:inline-block;min-width:1.5em;text-align:center;font:inherit;font-size:10px;line-height:1.4;padding:0 4px;border:1px solid var(--line-hover);border-radius:4px;color:var(--dim);background:var(--inset)}.btn.dopt .dkey{margin-right:6px}.btn.dopt.on .dkey{border-color:var(--link);color:var(--fg)}.danswer-wrap{position:relative}.danswer-wrap .dkey-text{position:absolute;top:6px;right:8px;pointer-events:none}.dlegend{margin-top:var(--space-3);padding-top:var(--space-2);border-top:1px solid var(--line);font-size:11px;line-height:1.9}.danswer:focus{outline:none;border-color:var(--line-hover)}.dfoot{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.dfoot .dattach input{display:none}.dfoot .dchip{font-size:11px;border:1px solid var(--line);border-radius:var(--badge-radius);padding:0 0 0 6px}.dfoot .dx{background:none;border:none;color:var(--dim);cursor:pointer;font:inherit}.dfoot .derr{font-size:11px}.btn.dsend{margin-left:auto;color:var(--fg);padding:2px 14px}.btn:disabled{cursor:default;opacity:0.6}.danswered{margin-top:6px}.thumb,.dimg,.mdimg{background:none;border:none;padding:0;cursor:zoom-in;font:inherit}.thumb{display:block;margin:4px 0}.thumb img{max-height:120px;max-width:240px;border:1px solid var(--line);border-radius:var(--radius);display:block}.lightbox{position:fixed;inset:0;z-index:20;background:rgba(0,0,0,0.85);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2)}.lightbox .lbimg{max-width:90vw;max-height:90vh;object-fit:contain;border-radius:var(--radius);box-shadow:0 8px 40px rgba(0,0,0,0.6)}.lightbox .lbclose{position:absolute;top:12px;right:16px;background:none;border:none;color:var(--fg);font-size:28px;line-height:1;cursor:pointer}.lightbox .lboriginal{color:var(--link);font-size:12px}.mdpage{background:var(--inset);border:1px solid var(--line);border-radius:6px;padding:8px 14px;margin:6px 0;line-height:1.5;overflow-wrap:anywhere}.mdpage h1,.mdpage h2,.mdpage h3,.mdpage h4{margin:12px 0 6px;line-height:1.25}.mdpage h1{font-size:18px}.mdpage h2{font-size:15px}.mdpage h3,.mdpage h4{font-size:13px}.mdpage p,.mdpage ul,.mdpage ol,.mdpage blockquote{margin:6px 0}.mdpage ul,.mdpage ol{padding-left:22px}.mdpage a{color:var(--link)}.mdpage code{background:var(--card);border-radius:3px;padding:0 3px}.mdpage pre.mdcode{background:var(--card);border:1px solid var(--line);border-radius:4px;padding:8px;max-width:100%;overflow-x:auto;white-space:pre;overflow-wrap:normal}.mdpage pre.mdcode code{padding:0;background:none}.mdpage blockquote{border-left:3px solid var(--line);padding-left:10px;color:var(--dim)}.mdpage img{max-width:100%;height:auto;border-radius:4px;display:block;margin:6px 0}.mdpage hr{border:0;border-top:1px solid var(--line)}.mdpage .mdtable{max-width:100%;overflow-x:auto}.mdpage table{border-collapse:collapse;margin:6px 0}.mdpage th,.mdpage td{border:1px solid var(--line);padding:3px 8px;text-align:left;white-space:normal;overflow-wrap:anywhere;min-width:12ch}.tabhead{margin:0 0 8px}.newtrap{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:12px;font-weight:normal;text-transform:none;letter-spacing:normal}.startcmds{margin:6px 0;font-size:11px;cursor:default}.reportview{width:100%;max-width:1100px;margin:0 auto;padding:20px 16px 48px;overflow-wrap:anywhere}.reportview h1{font-size:18px;margin:0 0 4px}.reportview .sub{color:var(--dim);font-size:12px;margin-bottom:10px}.reportview .sec{color:var(--dim);text-transform:uppercase;letter-spacing:0.08em;font-size:11px;margin:14px 0 4px}.reportview .mdpage{padding:12px 20px}@media(max-width:600px){.reportview{padding:12px 0 32px}.reportview .mdpage{padding:8px 12px}}.stats{display:flex;flex-direction:column;gap:var(--space-4);max-width:100%}.stats h2{margin:0 0 var(--space-2)}.stat-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:var(--space-2)}.stat-tile{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.stat-tile .n{font-size:22px;font-weight:bold;color:var(--fg)}.stats-empty{display:flex;align-items:center;gap:var(--space-4);background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--space-4) var(--space-4) var(--space-3)}.stats-empty .pet-art{flex:none;margin-top:6px}.heat{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad);min-width:0}.heat-scroll{overflow-x:auto;padding:2px 0 4px}.heatmap{border-collapse:separate;border-spacing:var(--heat-gap);width:auto;margin:0;background:none;border:0;border-radius:0;overflow:visible}.heatmap td{padding:0;border:0;vertical-align:middle;font-size:10px;line-height:1;color:var(--dim)}.heatmap .month{position:relative;height:14px}.heatmap .month span{position:absolute;left:0;bottom:3px;white-space:nowrap}.heatmap .wd{position:sticky;left:0;z-index:1;background:var(--card);padding-right:var(--space-1);white-space:nowrap}.heatmap .day,.heatmap .pad,.heat-legend .swatch{width:var(--heat-cell);min-width:var(--heat-cell);height:var(--heat-cell);border-radius:2px}.heatmap .day{position:relative;cursor:default;outline:1px solid rgba(255,255,255,0.04);outline-offset:-1px}.heatmap .day:focus-visible{outline:2px solid var(--link);outline-offset:0}.l0{background:var(--heat-0)}.l1{background:var(--heat-1)}.l2{background:var(--heat-2)}.l3{background:var(--heat-3)}.l4{background:var(--heat-4)}.heatmap .day:hover::after,.heatmap .day:focus::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);z-index:4;background:var(--bg);border:1px solid var(--line-hover);border-radius:var(--badge-radius);color:var(--fg);font-size:11px;padding:3px 7px;white-space:nowrap;pointer-events:none}.heatmap .day.below:hover::after,.heatmap .day.below:focus::after{bottom:auto;top:calc(100% + 6px)}.heatmap .day.tl:hover::after,.heatmap .day.tl:focus::after{left:0;transform:none}.heatmap .day.tr:hover::after,.heatmap .day.tr:focus::after{left:auto;right:0;transform:none}.heat-foot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--space-2);font-size:11px;margin-top:var(--space-1)}.heat-legend{display:inline-flex;align-items:center;gap:var(--heat-gap);color:var(--dim);margin-left:auto}.heat-legend .swatch{display:inline-block}.heat-legend .swatch:first-of-type{margin-left:var(--space-1)}.heat-legend .swatch:last-of-type{margin-right:var(--space-1)}.top-traps{background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.top-traps ol{list-style:none;margin:0;padding:0;display:grid;gap:6px}.top-traps li{display:grid;grid-template-columns:minmax(0,14em) minmax(40px,32em) auto;justify-content:start;align-items:center;gap:var(--space-3)}.top-traps .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.top-traps .bar{height:6px;background:var(--inset);border-radius:3px;overflow:hidden}.top-traps .bar span{display:block;height:100%;background:var(--lobstah)}.top-traps .n{color:var(--dim);white-space:nowrap}@media(max-width:600px){.tabs{flex-wrap:wrap}.tabs a{white-space:nowrap}}</style>\n </head>\n <body>\n <!-- The page is rendered by Preact (src/components/app.ts): header, tabs, controls, the five tab pages, footer, lobs, modal overlay. -->\n <script>"use strict";(()=>{var Ke,y,Sn,zr,W,bn,Dn,xn,bt,je,ve,Gn,wt,yt,_t,Jr,We={},qe=[],Yr=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Ve=Array.isArray;function L(e,t){for(var n in t)e[n]=t[n];return e}function St(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Z(e,t,n){var s,r,o,a={};for(o in t)o=="key"?s=t[o]:o=="ref"?r=t[o]:a[o]=t[o];if(arguments.length>2&&(a.children=arguments.length>3?Ke.call(arguments,2):n),typeof e=="function"&&e.defaultProps!=null)for(o in e.defaultProps)a[o]===void 0&&(a[o]=e.defaultProps[o]);return Be(e,a,s,r,null)}function Be(e,t,n,s,r){var o={type:e,props:t,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++Sn,__i:-1,__u:0};return r==null&&y.vnode!=null&&y.vnode(o),o}function ee(e){return e.children}function Ue(e,t){this.props=e,this.context=t}function V(e,t){if(t==null)return e.__?V(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type=="function"?V(e):null}function Qr(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,s=[],r=[],o=L({},t);o.__v=t.__v+1,y.vnode&&y.vnode(o),Dt(e.__P,o,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,s,n??V(t),!!(32&t.__u),r),o.__v=t.__v,o.__.__k[o.__i]=o,Mn(s,o,r),t.__e=t.__=null,o.__e!=n&&Cn(o)}}function Cn(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),Cn(e)}function yn(e){(!e.__d&&(e.__d=!0)&&W.push(e)&&!Fe.__r++||bn!=y.debounceRendering)&&((bn=y.debounceRendering)||Dn)(Fe)}function Fe(){try{for(var e,t=1;W.length;)W.length>t&&W.sort(xn),e=W.shift(),t=W.length,Qr(e)}finally{W.length=Fe.__r=0}}function Tn(e,t,n,s,r,o,a,l,u,c,d){var h,p,m,f,$,_,x=s&&s.__k||qe,b=t.length;for(u=Xr(n,t,x,u,b),h=0;h<b;h++)(m=n.__k[h])!=null&&(p=m.__i!=-1&&x[m.__i]||We,m.__i=h,_=Dt(e,m,p,r,o,a,l,u,c,d),f=m.__e,m.ref&&p.ref!=m.ref&&(p.ref&&xt(p.ref,null,m),d.push(m.ref,m.__c||f,m)),$==null&&f!=null&&($=f),4&m.__u?(u=An(m,u,e),p.__e&&(p.__e=null)):typeof m.type=="function"&&_!==void 0?u=_:f&&(u=f.nextSibling),m.__u&=-7);return n.__e=$,u}function Xr(e,t,n,s,r){var o,a,l,u,c,d=n.length,h=d,p=0;for(e.__k=new Array(r),o=0;o<r;o++)(a=t[o])!=null&&typeof a!="boolean"&&typeof a!="function"?(typeof a=="string"||typeof a=="number"||typeof a=="bigint"||a.constructor==String?a=e.__k[o]=Be(null,a,null,null,null):Ve(a)?a=e.__k[o]=Be(ee,{children:a},null,null,null):a.constructor===void 0&&a.__b>0?a=e.__k[o]=Be(a.type,a.props,a.key,a.ref?a.ref:null,a.__v):e.__k[o]=a,u=o+p,a.__=e,a.__b=e.__b+1,l=null,(c=a.__i=Zr(a,n,u,h))!=-1&&(h--,(l=n[c])&&(l.__u|=2)),l==null||l.__v==null?(c==-1&&(r>d?p--:r<d&&p++),typeof a.type!="function"&&(a.__u|=4)):c!=u&&(c==u-1?p--:c==u+1?p++:(c>u?p--:p++,a.__u|=4))):e.__k[o]=null;if(h)for(o=0;o<d;o++)(l=n[o])!=null&&(2&l.__u)==0&&(l.__e==s&&(s=V(l)),In(l,l));return s}function An(e,t,n){var s,r;if(typeof e.type=="function"){for(s=e.__k,r=0;s&&r<s.length;r++)s[r]&&(s[r].__=e,t=An(s[r],t,n));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=V(e)),t=n.insertBefore(e.__e,t||null));do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function Zr(e,t,n,s){var r,o,a,l=e.key,u=e.type,c=t[n],d=c!=null&&(2&c.__u)==0;if(c===null&&l==null||d&&l==c.key&&u==c.type)return n;if(s>(d?1:0)){for(r=n-1,o=n+1;r>=0||o<t.length;)if((c=t[a=r>=0?r--:o++])!=null&&(2&c.__u)==0&&l==c.key&&u==c.type)return a}return-1}function _n(e,t,n){t[0]=="-"?e.setProperty(t,n??""):e[t]=n==null?"":typeof n!="number"||Yr.test(t)?n:n+"px"}function He(e,t,n,s,r){var o,a;e:if(t=="style")if(typeof n=="string")e.style.cssText=n;else{if(typeof s=="string"&&(e.style.cssText=s=""),s)for(t in s)n&&t in n||_n(e.style,t,"");if(n)for(t in n)s&&n[t]==s[t]||_n(e.style,t,n[t])}else if(t[0]=="o"&&t[1]=="n")o=t!=(t=t.replace(Gn,"$1")),a=t.toLowerCase(),t=a in e||t=="onFocusOut"||t=="onFocusIn"?a.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+o]=n,n?s?n[ve]=s[ve]:(n[ve]=wt,e.addEventListener(t,o?_t:yt,o)):e.removeEventListener(t,o?_t:yt,o);else{if(r=="http://www.w3.org/2000/svg")t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(t!="width"&&t!="height"&&t!="href"&&t!="list"&&t!="form"&&t!="tabIndex"&&t!="download"&&t!="rowSpan"&&t!="colSpan"&&t!="role"&&t!="popover"&&t in e)try{e[t]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&n==1?"":n))}}function wn(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[je]==null)t[je]=wt++;else if(t[je]<n[ve])return;return n(y.event?y.event(t):t)}}}function Dt(e,t,n,s,r,o,a,l,u,c){var d,h,p,m,f,$,_,x,b,P,ge,K,$e,kn,Ne,kt,I=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(u=!!(32&n.__u),o=[l=t.__e=n.__e]),(d=y.__b)&&d(t);e:if(typeof I=="function"){h=a.length;try{if(b=t.props,P=I.prototype&&I.prototype.render,ge=(d=I.contextType)&&s[d.__c],K=d?ge?ge.props.value:d.__:s,n.__c?x=(p=t.__c=n.__c).__=p.__E:(P?t.__c=p=new I(b,K):(t.__c=p=new Ue(b,K),p.constructor=I,p.render=to),ge&&ge.sub(p),p.state||(p.state={}),p.__n=s,m=p.__d=!0,p.__h=[],p._sb=[]),P&&p.__s==null&&(p.__s=p.state),P&&I.getDerivedStateFromProps!=null&&(p.__s==p.state&&(p.__s=L({},p.__s)),L(p.__s,I.getDerivedStateFromProps(b,p.__s))),f=p.props,$=p.state,p.__v=t,m)P&&I.getDerivedStateFromProps==null&&p.componentWillMount!=null&&p.componentWillMount(),P&&p.componentDidMount!=null&&p.__h.push(p.componentDidMount);else{if(P&&I.getDerivedStateFromProps==null&&b!==f&&p.componentWillReceiveProps!=null&&p.componentWillReceiveProps(b,K),t.__v==n.__v||!p.__e&&p.shouldComponentUpdate!=null&&p.shouldComponentUpdate(b,p.__s,K)===!1){t.__v!=n.__v&&(p.props=b,p.state=p.__s,p.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(X){X&&(X.__=t)}),qe.push.apply(p.__h,p._sb),p._sb=[],p.__h.length&&a.push(p),l=V(n);break e}p.componentWillUpdate!=null&&p.componentWillUpdate(b,p.__s,K),P&&p.componentDidUpdate!=null&&p.__h.push(function(){p.componentDidUpdate(f,$,_)})}if(p.context=K,p.props=b,p.__P=e,p.__e=!1,$e=y.__r,kn=0,P)p.state=p.__s,p.__d=!1,$e&&$e(t),d=p.render(p.props,p.state,p.context),qe.push.apply(p.__h,p._sb),p._sb=[];else do p.__d=!1,$e&&$e(t),d=p.render(p.props,p.state,p.context),p.state=p.__s;while(p.__d&&++kn<25);p.state=p.__s,p.getChildContext!=null&&(s=L(L({},s),p.getChildContext())),P&&!m&&p.getSnapshotBeforeUpdate!=null&&(_=p.getSnapshotBeforeUpdate(f,$)),Ne=d!=null&&d.type===ee&&d.key==null?Pn(d.props.children):d,l=Tn(e,Ve(Ne)?Ne:[Ne],t,n,s,r,o,a,l,u,c),p.base=t.__e,t.__u&=-161,p.__h.length&&a.push(p),x&&(p.__E=p.__=null)}catch(X){if(a.length=h,t.__v=null,u||o!=null){if(X.then){for(t.__u|=u?160:128;l&&l.nodeType==8&&l.nextSibling;)l=l.nextSibling;o!=null&&(o[o.indexOf(l)]=null),t.__e=l}else if(o!=null)for(kt=o.length;kt--;)St(o[kt])}else t.__e=n.__e;t.__k==null&&(t.__k=n.__k||[]),X.then||Rn(t),y.__e(X,t,n)}}else o==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):l=t.__e=eo(n.__e,t,n,s,r,o,a,u,c);return(d=y.diffed)&&d(t),128&t.__u?void 0:l}function Rn(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(Rn))}function Mn(e,t,n){for(var s=0;s<n.length;s++)xt(n[s],n[++s],n[++s]);y.__c&&y.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(o){o.call(r)})}catch(o){y.__e(o,r.__v)}})}function Pn(e){return typeof e!="object"||e==null||e.__b>0?e:Ve(e)?e.map(Pn):e.constructor!==void 0?null:L({},e)}function eo(e,t,n,s,r,o,a,l,u){var c,d,h,p,m,f,$,_=n.props||We,x=t.props,b=t.type;if(b=="svg"?r="http://www.w3.org/2000/svg":b=="math"?r="http://www.w3.org/1998/Math/MathML":r||(r="http://www.w3.org/1999/xhtml"),o!=null){for(c=0;c<o.length;c++)if((m=o[c])&&"setAttribute"in m==!!b&&(b?m.localName==b:m.nodeType==3)){e=m,o[c]=null;break}}if(e==null){if(b==null)return document.createTextNode(x);e=document.createElementNS(r,b,x.is&&x),l&&(y.__m&&y.__m(t,o),l=!1),o=null}if(b==null)_===x||l&&e.data==x||(e.data=x);else{if(o=b=="textarea"&&x.defaultValue!=null?null:o&&Ke.call(e.childNodes),!l&&o!=null)for(_={},c=0;c<e.attributes.length;c++)_[(m=e.attributes[c]).name]=m.value;for(c in _)m=_[c],c=="dangerouslySetInnerHTML"?h=m:c=="children"||c in x||c=="value"&&"defaultValue"in x||c=="checked"&&"defaultChecked"in x||He(e,c,null,m,r);for(c in x)m=x[c],c=="children"?p=m:c=="dangerouslySetInnerHTML"?d=m:c=="value"?f=m:c=="checked"?$=m:l&&typeof m!="function"||_[c]===m||He(e,c,m,_[c],r);if(d)l||h&&(d.__html==h.__html||d.__html==e.innerHTML)||(e.innerHTML=d.__html),t.__k=[];else if(h&&(e.innerHTML=""),Tn(t.type=="template"?e.content:e,Ve(p)?p:[p],t,n,s,b=="foreignObject"?"http://www.w3.org/1999/xhtml":r,o,a,o?o[0]:n.__k&&V(n,0),l,u),o!=null)for(c=o.length;c--;)St(o[c]);l&&b!="textarea"||(c="value",b=="progress"&&f==null?e.removeAttribute("value"):f!=null&&(f!==e[c]||b=="progress"&&!f||b=="option"&&f!=_[c])&&He(e,c,f,_[c],r),c="checked",$!=null&&$!=e[c]&&He(e,c,$,_[c],r))}return e}function xt(e,t,n){try{if(typeof e=="function"){var s=typeof e.__u=="function";s&&e.__u(),s&&t==null||(e.__u=e(t))}else e.current=t}catch(r){y.__e(r,n)}}function In(e,t,n){var s,r;if(y.unmount&&y.unmount(e),(s=e.ref)&&(s.current&&s.current!=e.__e||xt(s,null,t)),(s=e.__c)!=null){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(o){y.__e(o,t)}s.base=s.__P=s.__n=null}if(s=e.__k)for(r=0;r<s.length;r++)s[r]&&In(s[r],t,n||typeof e.type!="function");n||St(e.__e),e.__c=e.__=e.__e=void 0}function to(e,t,n){return this.constructor(e,n)}function Gt(e,t,n){var s,r,o,a;t==document&&(t=document.documentElement),y.__&&y.__(e,t),r=(s=typeof n=="function")?null:n&&n.__k||t.__k,o=[],a=[],Dt(t,e=(!s&&n||t).__k=Z(ee,null,[e]),r||We,We,t.namespaceURI,!s&&n?[n]:r?null:t.firstChild?Ke.call(t.childNodes):null,o,!s&&n?n:r?r.__e:t.firstChild,s,a),Mn(o,e,a),e.props.children=null}Ke=qe.slice,y={__e:function(e,t,n,s){for(var r,o,a;t=t.__;)if((r=t.__c)&&!r.__)try{if((o=r.constructor)&&o.getDerivedStateFromError!=null&&(r.setState(o.getDerivedStateFromError(e)),a=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,s||{}),a=r.__d),a)return r.__E=r}catch(l){e=l}throw e}},Sn=0,zr=function(e){return e!=null&&e.constructor===void 0},Ue.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=L({},this.state),typeof e=="function"&&(e=e(L({},n),this.props)),e&&L(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),yn(this))},Ue.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),yn(this))},Ue.prototype.render=ee,W=[],Dn=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,xn=function(e,t){return e.__v.__b-t.__v.__b},Fe.__r=0,bt=Math.random().toString(8),je="__d"+bt,ve="__a"+bt,Gn=/(PointerCapture)$|Capture$/i,wt=0,yt=wn(!1),_t=wn(!0),Jr=0;var te=e=>e>999?"999+":String(e);function ne(e){return e.harness==="codex"?!!e.desktopThread||e.link?.startsWith("codex://threads/")===!0||e.window?.bundleId==="com.openai.codex":e.harness==="claude"?e.window?.entrypoint==="claude-desktop"||!e.window?.entrypoint&&e.link?.startsWith("claude://claude.ai/")===!0:!1}function Hn(e){let{harness:t,sessionId:n}=e;if(!ne(e)&&n){if(t==="codex")return"codex resume "+n;if(t==="claude")return"claude --resume "+n}}function no(e){return{id:e,lane:"work",bucket:"done",repo:"",title:"",verb:"unknown",sort:0}}var En=new WeakMap;function Ct(e,t){let n=e.dispatches||[],s=En.get(n);return s||En.set(n,s=new Map(n.map(r=>[r.id,r]))),{...t,catches:(t.catches||[]).map(r=>s.get(r)??no(r))}}function E(e){if(!e)return"dim";let t=e.state||"open";return t==="open"&&e.merge?"pr-"+e.merge:t==="open"&&e.tone&&e.tone!=="ok"?e.tone:"pr-"+t}var se=["deck","dispatches","traps","prs","reports","notices","stats"];function jn(e){let t=String(e||"").replace(/^#/,"");return se.includes(t)?t:"deck"}var Tt=e=>`#decision/${encodeURIComponent(e)}`;function re(e){let t=/^#?decision\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var At=(e,t,n)=>`/attachment/dispatch/${encodeURIComponent(e)}/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,Bn=(e,t)=>`/attachment/trap/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,Un=e=>/\\.(png|jpe?g|gif|webp)$/i.test(e),Rt=(e,t)=>`/decision/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function ze(e,t){let n=new Map(t.map(r=>[r.key,r])),s=[];for(let r of e)if(r.kind==="decision"){let o=n.get(r.key);if(!o)continue;s.push({kind:"decision",key:o.key,title:o.title,detail:o.detail,options:o.options,attachments:o.attachments,...o.dispatch?{dispatch:o.dispatch,lane:o.lane??"work"}:{},...o.repo?{repo:o.repo}:{},at:o.askedAt,...o.viewedAt??r.viewedAt?{viewedAt:o.viewedAt??r.viewedAt}:{}})}else r.kind==="question"&&s.push({kind:"question",key:r.key,verb:r.verb,note:r.note||r.verb,dispatch:r.id,lane:r.lane,...r.repo?{repo:r.repo}:{},at:r.at??"",...r.viewedAt?{viewedAt:r.viewedAt}:{}});return s.sort((r,o)=>o.at.localeCompare(r.at)||r.key.localeCompare(o.key))}function Wn(e){let t=(e.text??"").split(`\n`).map(n=>n.trim()).find(Boolean)??"";return[e.option,t&&(t.length>80?t.slice(0,79)+"\\u2026":t),e.files?`${e.files} file${e.files===1?"":"s"}`:""].filter(Boolean).join(" \\xB7 ")}function qn(e,t){return(e.reports||[]).find(n=>n.key===`report:${t.lane}:${t.id}`)}function ke(e){return e.author==="helm"?"":e.trap?e.trap:e.author==="headless"?e.dispatch?e.dispatch.slice(0,8):"":e.author}var On=(e,t)=>+!!e.acked-+!!t.acked||t.filedAt.localeCompare(e.filedAt),C=e=>`/report/${encodeURIComponent(e)}`;function be(e){let t=/^#?report\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}function Fn(e){return typeof e!="string"?!1:e===""?!0:e.length>1024||!e.startsWith("#")||/[\\s\\x00-\\x1f\\x7f]/.test(e)?!1:se.includes(e.slice(1))||re(e)!==null||be(e)!==null}function Kn(e){let t=/^\\/report\\/([^/?#]+)\\/?$/.exec(e);if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var Vn=e=>`/report/${encodeURIComponent(e)}/md`,Mt=(e,t)=>`/report/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`,Pt={dispatches:[],notices:[],prs:[],stacks:[]};function zn(e,t){if(t.kind==="dispatches"){let r=new Set(e.dispatches.map(o=>o.lane+":"+o.id));return{...e,dispatches:[...e.dispatches,...t.items.filter(o=>!r.has(o.lane+":"+o.id))]}}if(t.kind==="notices"){let r=new Set(e.notices.map(o=>o.seq));return{...e,notices:[...e.notices,...t.items.filter(o=>!r.has(o.seq))]}}let n=new Set(e.prs.map(r=>r.key)),s=new Set(e.stacks.map(r=>r.id));return{...e,prs:[...e.prs,...t.items.filter(r=>!n.has(r.key))],stacks:[...e.stacks,...t.stacks.filter(r=>!s.has(r.id))]}}function Jn(e,t){if(t===Pt||!t.dispatches.length&&!t.notices.length&&!t.prs.length)return e;let n=new Set(e.dispatches.map(a=>a.lane+":"+a.id)),s=new Set(e.notices.map(a=>a.seq)),r=new Set(e.prs.map(a=>a.key)),o=new Set(e.stacks.map(a=>a.id));return{...e,dispatches:[...e.dispatches,...t.dispatches.filter(a=>!n.has(a.lane+":"+a.id))],notices:[...e.notices,...t.notices.filter(a=>!s.has(a.seq))],prs:[...e.prs,...t.prs.filter(a=>!r.has(a.key))],stacks:[...e.stacks,...t.stacks.filter(a=>!o.has(a.id))]}}function Yn(e,t,n){return Math.max(0,(e.older?.[n]??0)-t[n].length)}function Qn(e,t){return{...e,now:t.now,daemon:e.daemon&&t.daemon!==void 0?{...e.daemon,heartbeat:t.daemon}:e.daemon,helms:e.helms.map(n=>t.helms[n.grounds]!==void 0?{...n,heartbeatAt:t.helms[n.grounds]}:n),traps:e.traps.map(n=>t.traps[n.trapId]?{...n,...t.traps[n.trapId]}:n)}}function Ln(e,t,n){return!!e&&n-Date.parse(e)>t}function Nn(e,t){if(t.lane&&e.lane!==t.lane||t.repo&&e.repo!==t.repo||t.verb&&e.verb!==t.verb)return!1;if(t.q){let n=t.q.toLowerCase();if(!(e.id+" "+(e.note||"")+" "+(e.title||"")+" "+(e.repo||"")+" "+(e.for||"")).toLowerCase().includes(n))return!1}return!0}function oe(e,t,n){if(!t)return null;if(t.type==="helm")return e.helms.find(r=>r.grounds===t.key)||null;if(t.type==="dispatch"){let r=e.dispatches.find(a=>a.lane+":"+a.id===t.key),o=n&&n.key===t.key?n.data:void 0;return r&&o?{...r,...o}:r??o??null}if(t.type==="pr")return(e.prs||[]).find(r=>r.key===t.key)||null;if(t.type==="settings")return{attentionKinds:e.attentionKinds||[],attentionError:e.attentionError};let s=e.traps.find(r=>r.trapId===t.key);return s?Ct(e,s):null}function Xn(e,t,n){let s=t.st,r=String(s.q||"").toLowerCase(),o=(...f)=>!r||f.join(" ").toLowerCase().includes(r),a=f=>({x:f,stale:Ln(f.heartbeatAt,18e5,n)}),l=oe(e,t.modal,t.detail),u=(f,$)=>!!f&&n-Date.parse(f)<=$,c=f=>Math.max(0,...(f.notices||[]).filter($=>$.kind==="trap-stowed"||$.kind==="trap-ghosted").map($=>Date.parse($.at)||0)),d=f=>f.live||!!f.starting||!!f.requested,h=[...e.traps||[]].sort((f,$)=>Number(d($))-Number(d(f))||Number($.live)-Number(f.live)||(f.live?(Date.parse(f.signedOnAt||"")||0)-(Date.parse($.signedOnAt||"")||0):c($)-c(f))||(f.name??f.trapId).localeCompare($.name??$.trapId)),p=h.filter(f=>(d(f)||(f.notices||[]).some($=>($.kind==="trap-stowed"||$.kind==="trap-ghosted")&&u($.at,36e5)))&&o(f.name,f.trapId,f.repo,f.worktree)),m=({ageSecs:f,...$})=>$;return{chips:{daemon:e.daemon,daemonStale:!!e.daemon&&Ln(e.daemon.heartbeat,9e4,n),helms:e.helms.map(a),stats:e.stats},deck:{view:s.view,decisions:ze(e.attention||[],e.decisions||[]).filter(f=>f.kind==="decision"?o(f.kind,f.repo,f.title,f.dispatch,f.detail):o(f.kind,f.repo,f.note,f.dispatch)),prAttention:(e.attention||[]).filter(f=>f.kind&&f.kind.startsWith("pr:")).map(m),landed:(e.landed||[]).filter(f=>u(f.at,864e5)&&o(f.repo,f.note,f.id)).sort((f,$)=>Date.parse($.at)-Date.parse(f.at)).slice(0,8),reports:(e.reports||[]).filter(f=>o(f.title,f.author,f.dispatch,f.repo)).sort(On),inflight:e.dispatches.filter(f=>f.bucket!=="done"&&Nn(f,{...s,lane:"",repo:"",verb:""})),traps:p.map(f=>a(Ct(e,f))),stacks:(e.stacks||[]).filter(f=>f.open&&o(f.repo,f.numbers.join(" "))),prs:(e.prs||[]).filter(f=>f.state==="OPEN"),error:e.attentionError},dispatches:{view:s.view,chain:s.chain,list:e.dispatches.filter(f=>Nn(f,s))},traps:{view:s.view,list:h.filter(f=>(!s.repo||f.repo===s.repo)&&o(f.name,f.trapId,f.repo,f.worktree,f.harness)).map(f=>a(Ct(e,f)))},prs:{view:s.view,stacks:(e.stacks||[]).filter(f=>!s.repo||f.repo===s.repo),prs:(e.prs||[]).filter(f=>(!s.repo||f.repo===s.repo)&&o(f.number,f.title,f.url,f.state,f.baseRefName,f.headRefName)),watches:(e.watches||[]).filter(f=>!String(f.key).startsWith("pr:"))},reports:{view:s.view,list:(e.reports||[]).filter(f=>(!s.repo||f.repo===s.repo)&&o(f.title,f.author,f.dispatch,f.repo)).sort(On)},notices:{list:(e.notices||[]).filter(f=>(!s.repo||!f.repo||f.repo===s.repo)&&(!s.noticeKind||f.kind===s.noticeKind)&&o(f.kind,f.text,f.repo))},foot:{version:e.version,repoUrl:e.repoUrl},modal:{modal:t.modal,item:l&&a(l),prefs:t.modal&&t.modal.type==="settings"?{view:s.view,lobs:s.lobs}:void 0}}}function Zn(e,t){let n=(e.prs||[]).find(l=>l.key===t);if(!n)return null;let s=(e.stacks||[]).find(l=>l.id===n.stackId),r=new Map((e.dispatches||[]).map(l=>[l.id,l])),o=(n.dispatchIds||[]).map(l=>{let u=r.get(l);return u?{id:l,verb:u.verb,modalKey:u.lane+":"+u.id}:{id:l,culled:!0}}),a=n.watch;return{pr:n,stack:s?{numbers:s.numbers,titles:s.numbers.map(l=>(e.prs||[]).find(u=>u.stackId===s.id&&u.number===l)?.title||""),position:n.position+1,size:s.numbers.length,floor:s.floor,nextNumber:s.nextNumber,nextMergeable:!!n.nextMergeable,blockedBy:n.blockedBy}:null,chain:o,watch:a?{key:a.key,owner:a.owner||"",lastCheckedAt:a.lastCheckedAt||null,lastError:a.lastError||null,cursor:a.cursor}:null}}function es(e){return e?{text:e.lastError?"failing":"watching",at:e.lastCheckedAt||null}:{text:"no watch",at:null}}function Je(e,t){return e.filter(n=>!t(n.key)).sort((n,s)=>n.at.localeCompare(s.at)||n.key.localeCompare(s.key))}function ts(e,t,n){return Je(e,t).filter(s=>!s.viewedAt&&!n(s.key))}function ns(){let e={view:"table",lane:"",repo:"",verb:"",q:"",lobs:!0,chain:!1,noticeKind:""};try{Object.assign(e,JSON.parse(localStorage.getItem("spyglass")||"{}"))}catch{}return e.view!=="table"&&e.view!=="cards"&&(e.view="table"),e.lobs=e.lobs!==!1,e}function ss(e){try{localStorage.setItem("spyglass",JSON.stringify(e))}catch{}}function rs(){try{return JSON.parse(localStorage.getItem("spyglass-lob-hidden")||"{}")||{}}catch{return{}}}function os(e){try{localStorage.setItem("spyglass-lob-hidden",JSON.stringify(e))}catch{}}var ye,Ye;function ae(e){if(e.snapshot)return(Ye?.snapshot!==e.snapshot||Ye.older!==e.older)&&(Ye={snapshot:e.snapshot,older:e.older,view:Jn(e.snapshot,e.older)}),Ye.view}var as=new Set,g=()=>ye;function It(e){ye=e}function k(e){ye={...ye,...e};for(let t of as)t(ye)}var Et=e=>{as.add(e)};function so(e,t){let n=ae(e);return n&&oe(n,t,e.detail)?!0:t.type==="dispatch"&&e.detail?.key===t.key&&!e.detail.error}function Qe(e){let{modal:t,drafts:n,older:s,detail:r,decisionModal:o}=g(),a=ze(e.attention||[],e.decisions||[]),l=new Set(a.map(c=>c.key)),u=Object.fromEntries(Object.entries(n).filter(([c])=>l.has(c)));k({snapshot:e,stale:!1,modal:t&&so({snapshot:e,older:s,detail:r},t)?t:null,...Object.keys(u).length!==Object.keys(n).length?{drafts:u}:{},...o?.key&&!l.has(o.key)&&!n[o.key]?.sent?{decisionModal:is(a,u,o.key)}:{}})}function is(e,t,n){let s=Je(e,o=>!!t[o]?.sent||o===n);if(!s.length)return null;let r=e.find(o=>o.key===n)?.at??"";return{key:(s.find(o=>o.at>r||o.at===r&&o.key>(n??""))??s[0]).key}}function Xe(){let e=ae(g());return e?ze(e.attention||[],e.decisions||[]):[]}function _e(){let{drafts:e}=g();return Je(Xe(),t=>!!e[t]?.sent)}function Ze(){let{drafts:e,viewedHere:t}=g();return ts(Xe(),n=>!!e[n]?.sent,n=>!!t[n])}function ie(e){let t=e??Ze()[0]?.key??_e()[0]?.key;t&&k({decisionModal:{key:t}})}function we(e){let t=g().decisionModal;if(!t?.key)return;let n=_e(),s=n.findIndex(o=>o.key===t.key),r=n[s+e];s>=0&&r&&k({decisionModal:{key:r.key}})}var le=()=>k({decisionModal:null}),Se=9;function ro(){let e=g().decisionModal?.key;return e?_e().find(t=>t.key===e):void 0}function ls(e){let t=ro();if(!t||e<1||e>Se)return!1;let n=g().drafts[t.key];if(n?.sending||n?.sent)return!1;let s=t.kind==="decision"?t.options:[];return e<=s.length?(A(t.key,{option:s[e-1],error:void 0}),document.querySelectorAll(".dmodal .dopt")[e-1]?.focus(),!0):e===s.length+1?(document.querySelector(".dmodal textarea.danswer")?.focus(),!0):!1}async function ds(e){let t=g();if(t.viewedHere[e]||(k({viewedHere:{...t.viewedHere,[e]:!0}}),Xe().find(s=>s.key===e)?.viewedAt))return;let n=t.snapshot?.focusToken;if(n)try{await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":n},body:JSON.stringify({kind:"decision-viewed",payload:{key:e}})})}catch{}}function cs(){k({alertDismissed:Ze().map(e=>e.key)})}function ps(e){let{snapshot:t}=g();k({stale:!1,...t?{snapshot:Qn(t,e)}:{}})}async function Lt(){let{modal:e}=g();if(e?.type!=="dispatch")return;let t=e.key,n=t.slice(t.indexOf(":")+1),s;try{let o=await fetch(`/data/dispatch/${encodeURIComponent(n)}`,{cache:"no-store"});s=o.ok?{data:await o.json()}:{error:o.status===404?"this dispatch is gone":`the detail answered ${o.status}`}}catch{s={error:"the detail could not be read"}}let r=g();r.modal?.type!=="dispatch"||r.modal.key!==t||s.error&&r.detail?.key===t&&r.detail.data||k({detail:{key:t,...s}})}var Ot=!1;async function De(){if(!Ot){Ot=!0;try{let e=await fetch("/data/stats",{cache:"no-store"});if(!e.ok)throw new Error(`/data/stats answered ${e.status}`);k({stats:await e.json(),statsError:null})}catch{k({statsError:"stats could not be read"})}finally{Ot=!1}}}var Nt=e=>{g().statsFocus!==e&&k({statsFocus:e})};async function us(e){let{olderLoading:t,older:n}=g();if(!t){k({olderLoading:e,olderError:null});try{let s=await fetch(`/data/older?kind=${e}&offset=${n[e].length}&limit=50`,{cache:"no-store"});if(!s.ok)throw new Error(`/data/older answered ${s.status}`);let r=await s.json();k({older:zn(g().older,r),olderLoading:null})}catch{k({olderLoading:null,olderError:{kind:e,text:"older records could not be read"}})}}}var fs=()=>({text:"",files:[]});function A(e,t){let n=g().drafts;k({drafts:{...n,[e]:{...n[e]??fs(),...t}}})}function ms(e,t){let n=g().drafts[e]?.option;A(e,{option:n===t?void 0:t,error:void 0})}var oo=e=>new Promise((t,n)=>{let s=new FileReader;s.onload=()=>t(String(s.result).replace(/^data:[^,]*,/,"")),s.onerror=()=>n(s.error),s.readAsDataURL(e)});async function Ht(e,t){let n=g().snapshot?.answerLimits,s=[...t??[]],r=g().drafts[e]?.files??[],o=[],a=[];for(let l of s){let u=(/\\.[^.]+$/.exec(l.name)?.[0]??"").toLowerCase();if(n&&!n.extensions.includes(u))o.push(`${l.name}: type not accepted`);else if(n&&l.size>n.maxBytes)o.push(`${l.name}: larger than ${n.maxBytes} bytes`);else if(n&&r.length+a.length>=n.maxFiles)o.push(`${l.name}: at most ${n.maxFiles} files`);else try{a.push({name:l.name,bytes:l.size,data:await oo(l)})}catch{o.push(`${l.name}: could not be read`)}}A(e,{files:[...g().drafts[e]?.files??[],...a],error:o.length?o.join("; "):void 0})}var ao={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};async function hs(e,t){let n=[...t.clipboardData?.items??[]],s=new Date().toISOString().replace(/[:.]/g,"-").replace(/-\\d{3}Z$/,"Z"),r=n.filter(o=>o.kind==="file"&&o.type.startsWith("image/")).map(o=>o.getAsFile()).filter(o=>o!==null).map((o,a,l)=>{let u=`pasted-${s}${l.length>1?`-${a+1}`:""}${ao[o.type]??".png"}`;return new File([o],u,{type:o.type})});r.length&&await Ht(e,r)}function gs(e,t){let n=(g().drafts[e]?.files??[]).filter((s,r)=>r!==t);A(e,{files:n})}async function et(e){let t=g().snapshot?.focusToken,n=g().drafts[e]??fs();if(!(n.sending||n.sent)){if(!n.option&&!n.text.trim()&&n.files.length===0){A(e,{error:"Choose an option, write an answer, or attach a file."});return}if(!t){A(e,{error:"This page has no answer token; reload it."});return}A(e,{sending:!0,error:void 0});try{let s=await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":t},body:JSON.stringify({kind:"decision-answer",payload:{key:e,...n.option?{option:n.option}:{},...n.text.trim()?{text:n.text}:{},files:n.files.map(a=>({name:a.name,data:a.data}))}})}),r=await s.json();if(!s.ok||!r.ok){A(e,{sending:!1,error:r.reason??`The answer was refused (${s.status}).`});return}A(e,{sending:!1,sent:Wn({option:n.option,text:n.text,files:n.files.length})}),g().decisionModal?.key===e&&k({decisionModal:is(Xe(),g().drafts,e)??{key:null}})}catch{A(e,{sending:!1,error:"The answer could not be sent."})}}}var $s=()=>k({stale:!0}),vs=(e,t)=>k({lightbox:{src:e,name:t}}),de=()=>k({lightbox:null});function O(e,t){let n=g(),s={type:e,key:t};if(e==="dispatch"){k({modal:s,detail:n.detail?.key===t?n.detail:{key:t}}),Lt();return}let r=ae(n);k({modal:!r||oe(r,s)?s:null,detail:null})}function ce(){k({modal:null,detail:null})}async function ks(e){let t=g().snapshot?.focusToken;if(t)try{let s=await(await fetch(`/api/focus/${encodeURIComponent(e)}`,{method:"POST",headers:{"x-lobstah-focus-token":t}})).json();k({focusResults:{...g().focusResults,[e]:s.message??s.reason??"Window focus failed."}})}catch{k({focusResults:{...g().focusResults,[e]:"Window focus failed."}})}}async function bs(e,t){let n=g().snapshot?.focusToken;if(!n)return"The glass has no page token yet.";try{let r=await(await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":n},body:JSON.stringify({kind:"trap-request",payload:{repo:e,harness:t}})})).json();if(!r.ok)return r.reason??"The request was refused."}catch{return"The request could not be sent."}try{Qe(await(await fetch("/data")).json())}catch{}}function N(e){let t={...g().prefs,...e};ss(t),k({prefs:t})}function ys(e){e!=="table"&&e!=="cards"||N({view:e})}var _s=e=>N({lobs:e==="on"});function ws(e,t){let n={...g().lobHidden,[e]:t};os(n),setTimeout(()=>k({lobHidden:n}),0)}async function Ss(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}var xs=function(e,t,n,s){var r;t[0]=0;for(var o=1;o<t.length;o++){var a=t[o++],l=t[o]?(t[0]|=a?1:2,n[t[o++]]):t[++o];a===3?s[0]=l:a===4?s[1]=Object.assign(s[1]||{},l):a===5?(s[1]=s[1]||{})[t[++o]]=l:a===6?s[1][t[++o]]+=l+"":a?(r=e.apply(l,xs(e,l,n,["",null])),s.push(r),l[0]?t[0]|=2:(t[o-2]=0,t[o]=r)):s.push(l)}return s},Ds=new Map;function Gs(e){var t=Ds.get(this);return t||(t=new Map,Ds.set(this,t)),(t=xs(this,t.get(e)||(t.set(e,t=(function(n){for(var s,r,o=1,a="",l="",u=[0],c=function(p){o===1&&(p||(a=a.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,"")))?u.push(0,p,a):o===3&&(p||a)?(u.push(3,p,a),o=2):o===2&&a==="..."&&p?u.push(4,p,0):o===2&&a&&!p?u.push(5,0,!0,a):o>=5&&((a||!p&&o===5)&&(u.push(o,0,a,r),o=6),p&&(u.push(o,p,0,r),o=6)),a=""},d=0;d<n.length;d++){d&&(o===1&&c(),c(d));for(var h=0;h<n[d].length;h++)s=n[d][h],o===1?s==="<"?(c(),u=[u],o=3):a+=s:o===4?a==="--"&&s===">"?(o=1,a=""):a=s+a[0]:l?s===l?l="":a+=s:s===\'"\'||s==="\'"?l=s:s===">"?(c(),o=1):o&&(s==="="?(o=5,r=a,a=""):s==="/"&&(o<5||n[d][h+1]===">")?(c(),o===3&&(u=u[0]),o=u,(u=u[0]).push(2,0,o),o=0):s===" "||s===" "||s===`\n`||s==="\\r"?(c(),o=2):a+=s),o===3&&a==="!--"&&(o=4,u=u[0])}return c(),u})(e)),t),arguments,[])).length>1?t:t[0]}var Cs=e=>Array.isArray(e)?e.map(Cs):e===""?null:e,io=(e,t,...n)=>Z(e,t,...n.map(Cs)),i=Gs.bind(io);var xe,w,jt,Ts,nt=0,Ls=[],D=y,As=D.__b,Rs=D.__r,Ms=D.diffed,Ps=D.__c,Is=D.unmount,Es=D.__;function Ut(e,t){D.__h&&D.__h(w,e,nt||t),nt=0;var n=w.__H||(w.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function z(e){return nt=1,lo(Hs,e)}function lo(e,t,n){var s=Ut(xe++,2);if(s.t=e,!s.__c&&(s.__=[n?n(t):Hs(void 0,t),function(l){var u=s.__N?s.__N[0]:s.__[0],c=s.t(u,l);u!==c&&(s.__N=[c,s.__[1]],s.__c.setState({}))}],s.__c=w,!w.__f)){var r=function(l,u,c){if(!s.__c.__H)return!0;var d=!1,h=s.__c.props!==l;if(s.__c.__H.__.some(function(m){if(m.__N){d=!0;var f=m.__[0];m.__=m.__N,m.__N=void 0,f!==m.__[0]&&(h=!0)}}),o){var p=o.call(this,l,u,c);return d?p||h:p}return!d||h};w.__f=!0;var o=w.shouldComponentUpdate,a=w.componentWillUpdate;w.componentWillUpdate=function(l,u,c){if(this.__e){var d=o;o=void 0,r(l,u,c),o=d}a&&a.call(this,l,u,c)},w.shouldComponentUpdate=r}return s.__N||s.__}function Wt(e,t){var n=Ut(xe++,3);!D.__s&&Ns(n.__H,t)&&(n.__=e,n.u=t,w.__H.__h.push(n))}function qt(e){return nt=5,Ft(function(){return{current:e}},[])}function Ft(e,t){var n=Ut(xe++,7);return Ns(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function co(){for(var e;e=Ls.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(tt),t.__h.some(Bt),t.__h=[]}catch(n){t.__h=[],D.__e(n,e.__v)}}}D.__b=function(e){w=null,As&&As(e)},D.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),Es&&Es(e,t)},D.__r=function(e){Rs&&Rs(e),xe=0;var t=(w=e.__c).__H;t&&(jt===w?(t.__h=[],w.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(tt),t.__h.some(Bt),t.__h=[],xe=0)),jt=w},D.diffed=function(e){Ms&&Ms(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Ls.push(t)!==1&&Ts===D.requestAnimationFrame||((Ts=D.requestAnimationFrame)||po)(co)),t.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),jt=w=null},D.__c=function(e,t){t.some(function(n){try{n.__h.some(tt),n.__h=n.__h.filter(function(s){return!s.__||Bt(s)})}catch(s){t.some(function(r){r.__h&&(r.__h=[])}),t=[],D.__e(s,n.__v)}}),Ps&&Ps(e,t)},D.unmount=function(e){Is&&Is(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(s){try{tt(s)}catch(r){t=r}}),n.__H=void 0,t&&D.__e(t,n.__v))};var Os=typeof requestAnimationFrame=="function";function po(e){var t,n=function(){clearTimeout(s),Os&&cancelAnimationFrame(t),setTimeout(e)},s=setTimeout(n,35);Os&&(t=requestAnimationFrame(n))}function tt(e){var t=w,n=e.__c;typeof n=="function"&&(e.__c=void 0,n()),w=t}function Bt(e){var t=w;e.__c=e.__(),w=t}function Ns(e,t){return!e||e.length!==t.length||t.some(function(n,s){return n!==e[s]})}function Hs(e,t){return typeof t=="function"?t(e):t}var uo=["none","minimal","low","medium","high","xhigh","max","ultra"],fo=["default","acceptEdits","plan","dontAsk","bypassPermissions","auto"];function js(e){return typeof e=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,127}$/.test(e)?e:null}function Bs(e,t){return typeof e=="string"&&t.includes(e)?e:null}function Kt(e={}){return{harness:js(e.harness),model:js(e.model),config:{effort:Bs(e.config?.effort,uo),permissionMode:Bs(e.config?.permissionMode,fo)},...typeof e.observedAt=="string"&&/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\.\\d{3}Z$/.test(e.observedAt)&&Number.isFinite(Date.parse(e.observedAt))?{observedAt:e.observedAt}:{}}}var J=e=>{if(!e)return"";let t=Math.max(0,(Date.now()-Date.parse(e))/1e3);return t<90?Math.round(t)+"s":t<5400?Math.round(t/60)+"m":t<172800?(t/3600).toFixed(1)+"h":Math.round(t/86400)+"d"},v=e=>i`<span data-age=${e??""}>${J(e)}</span>`;function H({worker:e,label:t,cls:n="badge"}){let s=Kt(e),r=[s.model??"model unknown",s.config.effort].filter(Boolean).join(" \\xB7 "),[o,a]=z(null),l=u=>{let c=u.currentTarget.getBoundingClientRect();a({left:Math.max(8,Math.min(c.left,window.innerWidth-280)),top:c.bottom+6})};return i`<span class=${n+" worker-harness"} tabindex="0" aria-label=${r}\n onMouseEnter=${l} onFocus=${l} onBlur=${()=>a(null)}\n onMouseLeave=${u=>{document.activeElement!==u.currentTarget&&a(null)}}\n onKeyDown=${u=>{u.key==="Escape"&&a(null)}}>\n ${t??s.harness??"unknown harness"}${o&&!g().modal&&i`<span class="worker-tooltip" role="tooltip" aria-hidden="true" style=${o}>${r}</span>`}\n </span>`}var Vt=e=>e.worker&&i`<${H} worker=${e.worker} />`;function rt({worker:e,headless:t=!1}){let n=Kt(e);return i`<section class="worker-details"><div class="sec">${t?"headless worker \\xB7 launch / observation":"worker observation"}</div><dl>\n <dt>harness</dt><dd>${n.harness??"unknown"}</dd>\n <dt>model</dt><dd>${n.model??"model unknown"}</dd>\n <dt>effort</dt><dd>${n.config.effort??"unknown"}</dd>\n <dt>permission mode</dt><dd>${n.config.permissionMode??"unknown"}</dd>\n <dt>observed</dt><dd>${n.observedAt??"unknown"}</dd>\n </dl></section>`}var ot=e=>e.activity&&i`<div class=${"activity"+(e.activity.stale?" stale":"")} title=${e.activity.stale?"no activity past the wedge threshold":e.activity.kind}>${e.activity.stale?"stale \\xB7 ":""}${e.activity.summary} \xB7 ${v(e.activity.at)} ago</div>`,mo=e=>e&&/^https?:\\/\\//i.test(e)?e:void 0,at=e=>{let t=e.waiting;if(!t)return;let n=mo(t.link),s=n;try{n&&(s=new URL(n).host+new URL(n).pathname.replace(/\\/$/,""))}catch{s=n}return i`<div class="waiting">${e.verb}: waiting on ${t.on} \xB7 ${v(t.since)}${n&&[" \\xB7 ",i`<a href=${n} target="_blank" rel="noopener noreferrer" onClick=${G}>${s}</a>`]}</div>`},ho=12,Us=e=>e!==void 0&&e.length>ho,j=e=>Us(e)?e:void 0,B=e=>Us(e)?" long":"",S=(e,t)=>()=>O(e,t),G=e=>e.stopPropagation();function Y(e){if(e.requested)return i`<span class="dim">Requested \u2014 no window yet</span>`;if(e.starting)return i`<span class="dim">${e.starting.failedAt?"Did not start":"Starting \\u2014 no window yet"}</span>`;let t=ne(e)&&!!e.link;if(!e.live)return t?i`<span class="winaction"><a class="btn open" href=${e.link} title="open this session in its app" onClick=${G}>\u2197 open</a></span>`:null;let n=g();return!n.snapshot?.focusSupported&&!e.link?i`<span class="dim">Window focus is not supported here</span>`:i`<span class="winaction"><button class="btn open" title="open this trap\'s window" onClick=${r=>{G(r),ks(e.trapId)}}>\u2197 open</button>${e.link&&!t&&[" ",i`<a href=${e.link} onClick=${G}>Session link</a>`]}${n.focusResults[e.trapId]&&[" ",i`<span class="dim">${n.focusResults[e.trapId]}</span>`]}</span>`}function M(e,t,n){return t.length?i`<div class="wrap"><table><tbody><tr>${e.map(s=>i`<th>${s}</th>`)}</tr>${t}</tbody></table></div>`:i`<div class="empty">${n}</div>`}function ue({kind:e,more:t}){return!t.left&&!t.error?null:i`<div class="older">${t.left>0&&i`<button class="btn" disabled=${t.loading} onClick=${()=>{us(e)}}>${t.loading?"loading\\u2026":`show ${Math.min(t.left,50)} older (of ${t.left})`}</button>`}${t.error&&i` <span class="bad">${t.error}</span>`}</div>`}function go({text:e,label:t,href:n}){let[s,r]=z(null),o=l=>async u=>{G(u),await Ss(e)&&(r(l),setTimeout(()=>r(null),1e3))},a=[t&&i`<span class="dim">${t}</span>`,n?i`<code><a href=${n} onClick=${G}>${e}</a></code>`:i`<code class=${s==="code"?"copied":void 0} title="click to copy" onClick=${o("code")}>${e}</code>`,i`<button title="copy" onClick=${o("button")}>${s==="button"?"\\u2713":"\\u29C9"}</button>`];return t?i`<span class="cmd inline">${a}</span>`:i`<div class="cmd">${a}</div>`}var T=(e,t,n,s)=>i`<${go} key=${t} text=${e} label=${n} href=${s} />`,zt=e=>{if(ne(e))return e.link?T(e.link,void 0,"desktop thread:",e.link):i`<span class="dim">desktop thread \u2014 open in the app</span>`;let t=Hn(e);return t?T(t):i`<span class="dim">Resume command unavailable</span>`},Ge=(e,t,n="thumb")=>i`<button\n type="button"\n class=${n}\n title=${"view "+t}\n onClick=${s=>{G(s),vs(e,t)}}\n >\n <img src=${e} alt=${t} loading="lazy" />\n </button>`,pe=(e,t)=>e.map(n=>[i`<div class="sub">${n.name} \xB7 ${n.type} \xB7 ${n.bytes} bytes</div>`,t&&Un(n.name)&&Ge(t(n.name),n.name),T(n.path)]),Ws=/\\bwt:([a-z0-9][a-z0-9-]*)/g,Jt=e=>g().snapshot?.trapNames?.[e],U=e=>e.replace(Ws,(t,n,s)=>{let r=Jt(n);return r&&!qs(e,s,t.length,r)?r:t}),qs=(e,t,n,s)=>e.slice(Math.max(0,t-s.length-2),t)===`${s} (`&&e[t+n]===")";function it(e){let t="wt:"+e,n=Jt(e)??t;return g().snapshot?.traps.some(r=>r.trapId===e)?i`<a class="trapname" href="#traps" title=${t} onClick=${r=>{r.preventDefault(),G(r),O("trap",e)}}>${n}</a>`:i`<span class="trapname" title=${t}>${n}</span>`}var st=e=>{let t=/^wt:([a-z0-9][a-z0-9-]*)$/.exec(e);return t?it(t[1]):e};function R(e,t=1/0){let n=[],s=0;for(let l of e.matchAll(Ws)){l.index>s&&n.push({text:e.slice(s,l.index)});let u=Jt(l[1]);n.push(u&&qs(e,l.index,l[0].length,u)?{text:l[0]}:{text:u??l[0],trapId:l[1]}),s=l.index+l[0].length}s<e.length&&n.push({text:e.slice(s)});let r=n.reduce((l,u)=>l+u.text.length,0),o=r>t?t-1:1/0,a=[];for(let l of n){if(o<=0)break;l.text.length<=o?a.push(l.trapId?it(l.trapId):l.text):a.push(l.text.slice(0,o)),o-=l.text.length}return r>t&&a.push("\\u2026"),a}var $o=e=>e.log.flatMap((t,n)=>[n?`\n`:"",t.at+" "+t.verb,...t.note?[" ",...R(t.note)]:[]]),vo=e=>"brief"in e;function Fs(e,t){let n=[e.elapsed&&`elapsed: ${e.elapsed}`,e.attempt&&`attempt: ${e.attempt}`,e.branch&&`branch: ${e.branch}`,e.lastCommit&&`last commit: ${e.lastCommit}`,e.aheadTrunk&&`commits: ${e.aheadTrunk}`,e.draftPr&&`draft PR: ${e.draftPr}`,e.updated&&`updated: ${e.updated}`].filter(Boolean).join(`\n`),s=i`${e.waiting&&[i`<div class="sec">waiting</div>`,at(e)]}${e.activity&&[i`<div class="sec">activity</div>`,ot(e)]}${n&&[i`<div class="sec">progress</div>`,i`<pre>${n}</pre>`]}`,r=e.evidence&&{...e.evidence};return r?.worker&&(delete r.worker,delete r.harness),vo(e)?i`${s}<div class="sec">brief</div><pre>${e.brief}</pre>${e.attachments.length>0&&[i`<div class="sec">attachments (${e.attachments.length})</div>`,pe(e.attachments,o=>At(e.lane,e.id,o))]}${e.messageAttachments.length>0&&[i`<div class="sec">message attachments (${e.messageAttachments.length})</div>`,pe(e.messageAttachments,o=>At(e.lane,e.id,o))]}${e.followUp&&[i`<div class="sec">forks</div>`,i`<pre>${e.followUp}</pre>`]}<div class="sec">log</div><div class="loglines">${e.log.length?$o(e):"no entries yet"}</div>${e.inbox.length>0&&[i`<div class="sec">inbox</div>`,i`<div class="loglines">${e.inbox.join(`\n---\n`)}</div>`]}${e.awaitingReply&&[i`<div class="sec">awaiting reply</div>`,i`<div>${e.awaitingReply.line} \xB7 from ${e.awaitingReply.from} \xB7 ${v(e.awaitingReply.sentAt)} ago</div>`]}${r&&[i`<div class="sec">evidence</div>`,i`<div class="loglines">${JSON.stringify(r)}</div>`]}`:i`${s}<div class="sec">brief</div><div class=${t?.error?"bad":"dim"}>${t?.error??"loading\\u2026"}</div>${e.followUp&&[i`<div class="sec">forks</div>`,i`<pre>${e.followUp}</pre>`]}${e.note&&[i`<div class="sec">last note</div>`,i`<div class="loglines">${R(e.note)}</div>`]}`}function Ce(e){return e.for?[st(e.for),e.evidence&&e.evidence.deliveredTo?[" ",i`<span class="ok">\u2713delivered</span>`]:[" ",i`<span class="warn">waiting</span>`]]:e.claimedBy?st(e.claimedBy):""}function fe(e){if(e.prList&&e.prList.length>1)return[e.prList.map((r,o)=>[o?" \\u2192 ":"",i`<a href=${r.url} target="_blank" rel="noopener" onClick=${G}>#${r.number}</a>`,r.badge&&[" ",i`<span class=${"badge "+E(r.badge)}>${r.badge.text}</span>`]]),e.prGate&&[" ",i`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]];let t=e.evidence&&(e.evidence.prUrl||e.evidence.pr&&e.evidence.pr.url);if(!t)return"";let n=e.prBadge,s=e.evidence&&e.evidence.prUrls&&e.evidence.prUrls.length>1?e.evidence.prUrls:void 0;return[s?s.map((r,o)=>[o?" ":"",i`<a href=${r} target="_blank" rel="noopener" onClick=${G}>#${r.split("/").pop()}</a>`]):i`<a href=${t} target="_blank" rel="noopener" onClick=${G}>PR</a>`,n&&[" ",i`<span class=${"badge "+E(n)} title=${"observed "+n.observedAt}>${n.text}</span>`],e.prGate&&[" ",i`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]]}var ko={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready","stack-ready":"stack ready",landed:"landed",watch:"watch"},Yt={"pr:review":"bad","pr:checks":"bad","pr:conflict":"pr-conflicts","pr:ready":"ok","stack-ready":"ok","pr:draft":"dim",watch:"warn"},Ks=e=>ko[e]||"";var lt=e=>i`<a href=${e.url} target="_blank" rel="noopener" onClick=${G}>#${e.number}</a>`,dt=e=>i`<span class="prname" title=${e.title||void 0}><b>#${e.number}</b>${e.title&&[" ",e.title]}</span>`;function me(e,t,n){return e.flatMap((s,r)=>{let o=t.get(s)||void 0,a=s===n?i`<b title=${o}>#${s}</b>`:i`<span title=${o}>#${s}</span>`;return r?[" \\u2192 ",a]:[a]})}function Te(e){let t=e.checks;return t.passed+"/"+t.total+" passed"+(t.failed?" \\xB7 "+t.failed+" failed":"")+(t.pending?" \\xB7 "+t.pending+" pending":"")}function ct(e){let t=e.review||{};return(e.reviewDecision||"")+(t.unresolvedThreads?" \\xB7 "+t.unresolvedThreads+" unresolved":"")+(t.changesRequested?" \\xB7 changes requested":"")}function Ae(e){return[e.mergeStateStatus,e.nextMergeable?[" \\xB7 ",i`<span class="ok">next mergeable</span>`]:e.blockedBy?" \\xB7 blocked by #"+e.blockedBy:""]}function Qt(e){let t=es(e);return e?[t.text," \\xB7 ",t.at?[v(t.at)," ago"]:"never checked"]:i`<span class="dim">${t.text}</span>`}function Re(e){if(e.requested)return{stale:!1,listen:[i`<span class="dot"></span>`,i`<span class="dim">requested</span>`],hb:i`<span class="dim">\u2014</span>`};if(e.starting)return{stale:!1,listen:e.starting.failedAt?[i`<span class="dot bad"></span>`,i`<span class="bad">start failed</span>`]:[i`<span class="dot warn"></span>`,"starting"],hb:i`<span class="dim">\u2014</span>`};if(!e.live)return{stale:!1,listen:[i`<span class="dot"></span>`,i`<span class="dim">signed off</span>`],hb:i`<span class="dim">\u2014</span>`};let t=Date.now()-Date.parse(e.heartbeatAt)>18e5,n=e.listening??(!!e.firstParkedAt&&!t);return{stale:t,listen:n?[i`<span class="dot ok"></span>`,"listening"]:[i`<span class="dot warn"></span>`,"not listening"],hb:i`<span class=${t?"bad":"ok"}>${t&&"stale "}${v(e.heartbeatAt)} ago</span>`}}function Xt(e){if(e.requested)return{kind:"requested",helmOn:!!g().snapshot?.helmOn};if(e.starting)return e.starting.failedAt?{kind:"start failed",reason:e.starting.reason??"no session signed on in time"}:{kind:"starting",deadline:e.starting.deadline};if(!e.live)return{kind:"signed off"};let t=e.claimed?e.catches.find(n=>n.id===e.claimed&&n.bucket==="active"):void 0;return t?t.waiting||t.verb==="paused"?{kind:"parked",current:t}:{kind:"working",current:t}:{kind:"idle",listening:e.listening??(!!e.firstParkedAt&&Date.now()-Date.parse(e.heartbeatAt??"")<=18e5)}}function bo(e){let t=Xt(e);return t.kind==="working"||t.kind==="idle"&&t.listening?"ok":t.kind==="start failed"?"bad":t.kind==="parked"||t.kind==="starting"?"warn":"dim"}var Vs=e=>e.waiting?`waiting on ${e.waiting.on}`:e.note||"waiting",zs=e=>e.title.slice(0,40)||"(no title)";function Me(e){let t=Xt(e),n=i`<span class=${"dot trapdot "+bo(e)}></span>`;if(t.kind==="requested")return[n,i`<span class="dim">${Js(e,t.helmOn)}</span>`];if(t.kind==="starting")return[n,"starting \\xB7 waiting for its session to sign on"];if(t.kind==="start failed")return[n,i`<span class="bad">start failed</span>`," \\xB7 ",t.reason];if(t.kind==="signed off")return[n,i`<span class="dim">signed off</span>`];if(t.kind==="idle")return[n,"idle \\xB7 ",t.listening?"listening":"not listening"];let s=t.current;return t.kind==="parked"?[n,"parked \\xB7 ",Vs(s)]:[n,"working \\xB7 ",i`<a href="#dispatches" onClick=${o=>{o.preventDefault(),G(o),O("dispatch",`${s.lane}:${s.id}`)}}>${s.id.slice(0,8)}</a>`," \\xB7 ",zs(s),s.activity&&[" \\xB7 ",s.activity.summary," ",v(s.activity.at)," ago"]]}var Js=(e,t)=>`requested \\xB7 ${e.repo??""} \\xB7 ${e.harness??""} \\xB7 ${t?"waiting for the helm":"waiting for a helm"}`;function Q(e){let t=e.starting?.commands;return t?.length?i`<div class="startcmds" onClick=${G}><div class="dim">start it: run one in a terminal</div>${t.map(n=>T(n.command,n.harness))}</div>`:null}function pt(){let t=g().snapshot?.repoKeys??[],[n,s]=z(!1),[r,o]=z(""),[a,l]=z("claude"),[u,c]=z(null),d=r||t[0]||"",h=async p=>{p.preventDefault();let m=await bs(d,a);c(m??null),m||s(!1)};return n?i`<form class="newtrap" onClick=${G} onSubmit=${h}>\n <label>repo <select name="repo" value=${d} onChange=${p=>o(p.target.value)}>${t.map(p=>i`<option value=${p}>${p}</option>`)}</select></label>\n <label>harness <select name="harness" value=${a} onChange=${p=>l(p.target.value)}><option value="claude">claude</option><option value="codex">codex</option></select></label>\n <button class="btn" type="submit" disabled=${!d}>Request</button>\n <button class="btn" type="button" onClick=${()=>s(!1)}>Cancel</button>\n ${u&&i`<span class="bad">${u}</span>`}\n </form>`:i`<span class="newtrap"><button class="btn" onClick=${p=>(G(p),s(!0),c(null))}>+ New trap</button></span>`}function ut(e){let t=Xt(e);if(t.kind==="requested")return Js(e,t.helmOn);if(t.kind==="starting")return`starting \\xB7 sign-on due by ${t.deadline}`;if(t.kind==="start failed")return`start failed \\xB7 ${t.reason}`;if(t.kind==="signed off")return"signed off";if(t.kind==="idle")return`idle \\xB7 ${t.listening?"listening":"not listening"}`;if(t.kind==="parked")return`parked \\xB7 ${Vs(t.current)}`;let n=t.current;return[`working \\xB7 ${n.id.slice(0,8)} \\xB7 ${zs(n)}`,n.activity&&`${n.activity.summary} ${J(n.activity.at)} ago`].filter(Boolean).join(" \\xB7 ")}function Zt(e){let t=e.messages.filter(n=>n.state==="pending").length;return e.messages.length?["\\u2709 "+e.messages.length,t>0&&[" ",i`<span class="warn">(${t} pending)</span>`]]:null}var yo=e=>()=>{window.open(C(e.key),"_blank","noopener")};function en(e){let t=ke(e);return{nodes:[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked?" \\xB7 acked":""],text:[t,`${J(e.filedAt)} ago`,e.acked?"acked":""].filter(Boolean).join(" \\xB7 ")}}function _o(e){let t=en(e);return i`<a key=${e.key} class=${"card"+(e.acked?" acked":"")} href=${C(e.key)} target="_blank" rel="noopener"><div class="top"><b title=${e.title}>${e.title}</b></div><div class="meta" title=${t.text}>${t.nodes}</div></a>`}function wo(e){return i`<tr key=${e.key} class=${"rowhead"+(e.acked?" acked":"")} onClick=${yo(e)}><td class="grow"><a href=${C(e.key)} target="_blank" rel="noopener" onClick=${t=>t.stopPropagation()}>${e.title}</a></td><td>${ke(e)}</td><td>${v(e.filedAt)}</td><td>${e.acked?"acked":""}</td></tr>`}function Ys({inp:e}){return e.view==="cards"?e.list.length?i`<div class="cards">${e.list.map(_o)}</div>`:i`<div class="empty">no reports match</div>`:M(["title","from","filed","acked"],e.list.map(wo),"no reports match")}function Zs(e){let t=e.trim();return/^(https?:\\/\\/|mailto:|#)/i.test(t)?t:void 0}function er(e){let t=e.trim();return/^[^/\\\\:?#]+$/.test(t)&&t!=="."&&t!==".."?t:void 0}function Qs(e,t,n,s){let r=0;for(let o=t;o<e.length;o++){if(e[o]==="\\\\"){o++;continue}if(e[o]===n)r++;else if(e[o]===s){if(r===0)return o;r--}}return-1}function Xs(e,t){let n=Qs(e,t+1,"[","]");if(n<0||e[n+1]!=="(")return;let s=Qs(e,n+2,"(",")");if(s<0)return;let r=e.slice(n+2,s).trim().replace(/\\s+"[^"]*"$/,"").replace(/^<(.*)>$/,"$1");return{text:e.slice(t+1,n),target:r,end:s+1}}function q(e){let t=[],n="",s=()=>{n&&t.push({t:"text",v:n}),n=""};for(let r=0;r<e.length;){let o=e[r];if(o==="\\\\"&&r+1<e.length&&/[\\\\`*_{}[\\]()#+\\-.!|<>~]/.test(e[r+1])){n+=e[r+1],r+=2;continue}if(o==="`"){let a=/^`+/.exec(e.slice(r))[0],l=e.indexOf(a,r+a.length);if(l>0){s(),t.push({t:"code",v:e.slice(r+a.length,l).replace(/^ (.*) $/,"$1")}),r=l+a.length;continue}}if(o==="!"&&e[r+1]==="["){let a=Xs(e,r+1);if(a){s(),t.push({t:"img",alt:a.text,src:a.target}),r=a.end;continue}}if(o==="["){let a=Xs(e,r);if(a){s(),t.push({t:"a",href:a.target,c:q(a.text)}),r=a.end;continue}}if((o==="*"||o==="_")&&e[r+1]===o){let a=e.indexOf(o+o,r+2);if(a>r+2){s(),t.push({t:"b",c:q(e.slice(r+2,a))}),r=a+2;continue}}if(o==="*"||o==="_"&&(r===0||!/\\w/.test(e[r-1]))){let a=r+1;for(;(a=e.indexOf(o,a))>0&&(e[a+1]===o||o==="_"&&/\\w/.test(e[a+1]??""));)a+=2;if(a>r+1&&e[r+1]!==" "){s(),t.push({t:"i",c:q(e.slice(r+1,a))}),r=a+1;continue}}if(o===`\n`){/ {2,}$/.test(n)||n.endsWith("\\\\")?(n=n.replace(/( {2,}|\\\\)$/,""),s(),t.push({t:"br"})):n+=" ",r++;continue}n+=o,r++}return s(),t}var tr=/^ {0,3}(`{3,}|~{3,})\\s*([^`\\s]*)/,nr=/^ {0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/,sr=/^ {0,3}([-*_])(\\s*\\1){2,}\\s*$/,sn=/^( {0,3})([-*+])\\s+(.*)$/,rn=/^( {0,3})(\\d{1,9})[.)]\\s+(.*)$/,ft=/^ {0,3}>\\s?(.*)$/,So=/^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;function tn(e){let t=e.trim();t.startsWith("|")&&(t=t.slice(1)),t.endsWith("|")&&!t.endsWith("\\\\|")&&(t=t.slice(0,-1));let n=[],s="";for(let r=0;r<t.length;r++)t[r]==="\\\\"&&t[r+1]==="|"?(s+="|",r++):t[r]==="|"?(n.push(s.trim()),s=""):s+=t[r];return n.push(s.trim()),n}var nn=e=>tr.test(e)||nr.test(e)||sr.test(e)||sn.test(e)||rn.test(e)||ft.test(e);function mt(e){let t=e.replace(/\\r\\n?/g,`\n`).replace(/\\t/g," ").split(`\n`),n=[],s=0;for(;s<t.length;){let r=t[s];if(!r.trim()){s++;continue}let o=tr.exec(r);if(o){let d=o[1],h=[];for(s++;s<t.length&&!new RegExp(`^ {0,3}${d[0]}{${d.length},}\\\\s*$`).test(t[s]);)h.push(t[s++]);s++,n.push({t:"code",lang:o[2]??"",v:h.join(`\n`)});continue}let a=nr.exec(r);if(a){n.push({t:"h",level:a[1].length,c:q(a[2])}),s++;continue}if(sr.test(r)){n.push({t:"hr"}),s++;continue}if(ft.test(r)){let d=[];for(;s<t.length&&t[s].trim()&&(ft.test(t[s])||!nn(t[s]));)d.push(ft.exec(t[s])?.[1]??t[s]),s++;n.push({t:"quote",c:mt(d.join(`\n`))});continue}let l=sn.exec(r),u=rn.exec(r);if(l||u){let d=!l,h=d?rn:sn,p=[];for(;s<t.length;){let m=t[s],f=h.exec(m);if(f&&f[1].length<=3){p.push([f[3]]),s++;continue}if(!m.trim()){if(s+1<t.length&&/^ {2,}\\S/.test(t[s+1])){p.at(-1).push(""),s++;continue}break}if(/^ {2,}\\S/.test(m)){p.at(-1).push(m.replace(/^ {2,4}/,"")),s++;continue}if(nn(m))break;p.at(-1).push(m.trim()),s++}n.push({t:"list",ordered:d,start:d?Number(u[2]):1,items:p.map(m=>mt(m.join(`\n`)))});continue}if(r.includes("|")&&s+1<t.length&&So.test(t[s+1])&&t[s+1].includes("-")){let d=tn(r),h=tn(t[s+1]).map(m=>m.startsWith(":")&&m.endsWith(":")?"center":m.endsWith(":")?"right":m.startsWith(":")?"left":"");s+=2;let p=[];for(;s<t.length&&t[s].trim()&&t[s].includes("|");){let m=tn(t[s++]);p.push(d.map((f,$)=>q(m[$]??"")))}n.push({t:"table",align:d.map((m,f)=>h[f]??""),head:d.map(q),rows:p});continue}let c=[];for(;s<t.length&&t[s].trim()&&!nn(t[s])&&!(c.length&&/^ {0,3}(=+|-+)\\s*$/.test(t[s]));)c.push(t[s++].replace(/^ +/,""));if(c.length===0){n.push({t:"p",c:q(r.trim())}),s++;continue}n.push({t:"p",c:q(c.join(`\n`))})}return n}function F(e,t){return t.map(n=>{switch(n.t){case"text":return n.v;case"code":return i`<code>${n.v}</code>`;case"b":return i`<strong>${F(e,n.c)}</strong>`;case"i":return i`<em>${F(e,n.c)}</em>`;case"br":return i`<br />`;case"a":{let s=Zs(n.href);return s?i`<a href=${s} target="_blank" rel="noopener noreferrer">${F(e,n.c)}</a>`:F(e,n.c)}case"img":{let s=er(n.src);return s?Ge(e(s),n.alt||s,"mdimg"):i`<span class="dim">[image not shown: ${n.alt||n.src}]</span>`}}})}function ht(e,t){return t.map(n=>{switch(n.t){case"h":{let s=F(e,n.c);return n.level===1?i`<h1>${s}</h1>`:n.level===2?i`<h2>${s}</h2>`:n.level===3?i`<h3>${s}</h3>`:i`<h4>${s}</h4>`}case"p":return i`<p>${F(e,n.c)}</p>`;case"code":return i`<pre class="mdcode"><code>${n.v}</code></pre>`;case"hr":return i`<hr />`;case"quote":return i`<blockquote>${ht(e,n.c)}</blockquote>`;case"list":{let s=n.items.map(r=>i`<li>${ht(e,r)}</li>`);return n.ordered?i`<ol start=${n.start}>${s}</ol>`:i`<ul>${s}</ul>`}case"table":return i`<div class="mdtable"><table><thead><tr>${n.head.map((s,r)=>i`<th style=${n.align[r]?"text-align:"+n.align[r]:void 0}>${F(e,s)}</th>`)}</tr></thead><tbody>${n.rows.map(s=>i`<tr>${s.map((r,o)=>i`<td style=${n.align[o]?"text-align:"+n.align[o]:void 0}>${F(e,r)}</td>`)}</tr>`)}</tbody></table></div>`}})}var Pe=new Map;function rr(e){let t=Pe.get(e);return t||(t=mt(e),Pe.set(e,t),Pe.size>8&&Pe.delete(Pe.keys().next().value)),t}function Do({r:e,text:t}){let n=t?.text!==void 0?ht(s=>Mt(e.key,s),rr(t.text)):t?.error?i`<div class="bad">${t.error}</div>`:i`<div class="dim">loading\u2026</div>`;return i`<div class="mdpage" data-report=${e.key}>${n}</div>`}function or({text:e,fileUrl:t}){return i`<div class="mdpage">${ht(t,rr(e))}</div>`}function on(e){let t=ke(e);return[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked&&[" \\xB7 ",i`<span class="ok">acked</span>`]]}function ar({r:e,text:t,heading:n}){return[n&&i`<div class="sec">report \xB7 ${e.title}</div>`,i`<div class="sub">${on(e)}</div>`,i`<${Do} r=${e} text=${t} />`,e.attachments.length>0&&[i`<div class="sec">report attachments (${e.attachments.length})</div>`,pe(e.attachments,s=>Mt(e.key,s))],!e.acked&&[i`<div class="sec">ack</div>`,T("lobstah attention ack "+e.key)]]}var xo=/\\.(png|jpe?g|gif|webp)$/i,Go=e=>{e.style.height="auto",e.style.height=e.scrollHeight+"px"};function Co(e,t){return t.length?i`<div class="dfiles">${t.map(n=>xo.test(n.name)?i`<span key=${n.name}>${Ge(Rt(e,n.name),n.name,"dimg")}</span>`:i`<div key=${n.name} class="dfile"><span>${n.name}</span> <span class="dim">\xB7 ${n.type} \xB7 ${n.bytes} bytes \xB7 </span><code>${n.path}</code></div>`)}</div>`:null}function To(e,t,n){let s=e.key,r=e.kind==="decision"?e.options:[],o=t?.text??"",a=t?.files??[],l=!!t?.sending,u=d=>d+1<=Se?String(d+1):void 0,c=u(r.length);return[r.length>0&&i`<div class="doptions">${r.map((d,h)=>{let p=u(h);return i`<button key=${d} type="button" class=${"btn dopt"+(t?.option===d?" on":"")} aria-pressed=${t?.option===d?"true":"false"} aria-keyshortcuts=${p} disabled=${l} onClick=${()=>ms(s,d)}>${p&&i`<kbd class="dkey" aria-hidden="true">${p}</kbd>`}<span class="dlabel">${d}</span></button>`})}</div>`,i`<div class="danswer-wrap">${c&&i`<kbd class="dkey dkey-text" aria-hidden="true">${c}</kbd>`}<textarea\n class="danswer"\n rows="2"\n aria-keyshortcuts=${c}\n aria-label=${r.length?"Your answer, in your own words":"Your answer"}\n placeholder=${r.length?"Add to your answer, or answer in your own words":"Your answer"}\n value=${o}\n disabled=${l}\n onInput=${d=>{let h=d.currentTarget;Go(h),A(s,{text:h.value,error:void 0})}}\n onPaste=${d=>{hs(s,d)}}\n ></textarea></div>`,i`<div class="dfoot">\n <label class="btn dattach" title="attach images or files">attach<input type="file" multiple accept=${n} disabled=${l} onChange=${d=>{let h=d.currentTarget;Ht(s,h.files).then(()=>{h.value=""})}} /></label>\n ${a.map((d,h)=>i`<span key=${d.name+h} class="dchip">${d.name}<button type="button" class="dx" title="remove" disabled=${l} onClick=${()=>gs(s,h)}>\xD7</button></span>`)}\n ${t?.error&&i`<span class="bad derr">${t.error}</span>`}\n <button type="button" class="btn dsend" disabled=${l} onClick=${()=>{et(s)}}>${l?"Sending\\u2026":"Send"}</button>\n </div>`]}var ir=e=>e.kind==="decision"?e.title:R(e.note);function Ao(e,t,n){return t?.sent?"answered":e.viewedAt||n?"read":"unread"}function an(e){let t=e.dispatch,n=e.lane??"work";return[t&&i`<a class="dlink" href="#" onClick=${r=>{r.preventDefault(),r.stopPropagation(),S("dispatch",n+":"+t)()}}>${t.slice(0,8)}</a>`,e.repo].filter(Boolean).flatMap((r,o)=>o?[" \\xB7 ",r]:[r])}function Ro(e,t,n,s){let r=Ao(e,t,n),o=()=>ie(e.key);return i`<li key=${e.key} class=${"drow "+r+(s?" focus":"")} data-decision=${e.key}>\n <button type="button" class="dopen" onClick=${o} aria-label=${`${r}: ${e.kind==="decision"?e.title:e.note}`}>\n ${e.kind==="question"&&i`<span class=${"badge "+(e.verb==="blocked"?"bad":"warn")}>${e.verb}</span>`}\n <b class="dtitle">${ir(e)}</b>\n </button>\n <span class="dmeta dim">${an(e)}</span>\n <span class="dage dim">${v(e.at)} ago</span>\n <span class=${"dstate "+r}>${r==="answered"?`answered \\xB7 ${t.sent}`:r}</span>\n </li>`}function lr({cards:e,drafts:t,focus:n,viewedHere:s,unread:r}){let o=e.length?i`<ul class="dlist">${e.map(a=>Ro(a,t[a.key],!!s[a.key],a.key===n))}</ul>`:i`<div class="empty">none</div>`;return i`<section class="decisions"><h2>decisions${r>0&&i`<span class="dbadge" aria-label=${`${r} new`}>${r}</span>`}</h2>${o}</section>`}function Mo(e){let t=Math.min(e,Se),n=e+1<=Se?String(e+1):void 0,s=[t>0&&[i`<kbd>1</kbd>`,t>1&&["\\u2013",i`<kbd>${t}</kbd>`]," choose"],n&&[i`<kbd>${n}</kbd>`," write"],t>0&&[i`<kbd>Enter</kbd>`," on a chosen option sends"],[i`<kbd>\u2190</kbd>`," ",i`<kbd>\u2192</kbd>`," previous / next"],[i`<kbd>Esc</kbd>`," leaves the text box, then closes"],[i`<kbd>d</kbd>`," opens decisions anywhere"]].filter(Boolean);return i`<div class="dlegend dim">${s.flatMap((r,o)=>o?[" \\xB7 ",r]:[r])}</div>`}var Po=\'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])\';function dr({open:e,order:t,drafts:n,extensions:s}){let r=qt(null),o=qt(null),a=!!e;Wt(()=>{if(a)return o.current=document.activeElement,r.current?.focus(),()=>{let m=o.current;m&&typeof m.focus=="function"&&document.contains(m)&&m.focus()}},[a]);let l=e?.key??null;if(Wt(()=>{l&&ds(l)},[l]),!e)return null;let u=m=>{if(m.key!=="Tab"||!r.current)return;let f=[...r.current.querySelectorAll(Po)];if(!f.length)return void m.preventDefault();let $=f[0],_=f[f.length-1];m.shiftKey&&(document.activeElement===$||document.activeElement===r.current)?(m.preventDefault(),_.focus()):!m.shiftKey&&document.activeElement===_&&(m.preventDefault(),$.focus())},c=l?t.find(m=>m.key===l):void 0,d=c?t.indexOf(c):-1,h=(m,f,$="")=>i`<div id="doverlay" class="open" onClick=${_=>_.target===_.currentTarget&&le()}>\n <div class="modal dmodal" role="dialog" aria-modal="true" aria-labelledby="dmodal-title" tabindex="-1" ref=${r} onKeyDown=${u} data-decision=${$}>\n <button type="button" class="x" aria-label="close" aria-keyshortcuts="Escape" onClick=${le}>\xD7</button>\n <h3 id="dmodal-title" class="sr-only">${m}</h3>\n ${f}\n </div>\n </div>`;if(!c)return h("All decisions answered",i`<div class="ddone" onClick=${le}><div class="ok">\u2713 All decisions answered.</div><div class="dim">Click anywhere or press Escape to close.</div></div>`);let p=n[c.key];return h(c.kind==="decision"?c.title:c.note,i`<div class="dnav">\n <button type="button" class="btn dprev" aria-label="previous decision" aria-keyshortcuts="ArrowLeft" disabled=${d<=0} onClick=${()=>we(-1)}>\u2039 prev</button>\n <span class="dpos" aria-live="polite">${d+1} of ${t.length}</span>\n <button type="button" class="btn dnext" aria-label="next decision" aria-keyshortcuts="ArrowRight" disabled=${d>=t.length-1} onClick=${()=>we(1)}>next \u203A</button>\n </div>\n <div class="dtop">\n ${c.kind==="question"&&i`<span class=${"badge "+(c.verb==="blocked"?"bad":"warn")}>${c.verb}</span>`}\n <b class="dtitle">${ir(c)}</b>\n <span class="dmeta dim">${an(c)}${an(c).length?" \\xB7 ":""}${v(c.at)} ago</span>\n </div>\n ${c.kind==="decision"&&c.detail.trim()&&i`<${or} text=${c.detail} fileUrl=${m=>Rt(c.key,m)} />`}\n ${c.kind==="decision"&&Co(c.key,c.attachments)}\n ${p?.sent?i`<div class="danswered ok">answered \xB7 ${p.sent}</div>`:To(c,p,s.join(","))}\n ${Mo(c.kind==="decision"?c.options.length:0)}`,c.key)}function cr({unread:e,dismissed:t}){let n=e.some(a=>!t.includes(a.key)),s=e.length>0&&n,r=e.length,o=`${r} new decision${r===1?"":"s"}`;return i`<div class="dalert-live" role="status" aria-live="polite">${s&&i`<div class="dalert">\n <button type="button" class="dalert-open" aria-keyshortcuts="d" onClick=${()=>ie()}><span class="dcount" aria-hidden="true">${r}</span> <span>${o}</span></button>\n <button type="button" class="dx" aria-label="dismiss" title="dismiss" onClick=${cs}>\xD7</button>\n </div>`}</div>`}function Lo(e,t){let n=e.badge&&(e.badge.worker?i`<${H} worker=${e.badge.worker} label=${e.badge.text} cls=${"badge "+(e.badge.tone||"dim")} />`:i`<span class=${"badge "+(e.badge.tone||"dim")+B(e.badge.text)} title=${j(e.badge.text)}>${e.badge.text}</span>`),s=e.worker&&i`<${H} worker=${e.worker} />`;if(e.href){let r=(t==="cards"?"card":"deckline click")+(e.acked?" acked":"");return t==="cards"?i`<a key=${e.key} class=${r} href=${e.href} target="_blank" rel="noopener"><div class="top"><b>${e.title}</b>${n}</div>${e.meta&&i`<div class="meta" title=${e.metaText}>${e.meta}</div>`}</a>`:i`<a key=${e.key} class=${r} href=${e.href} target="_blank" rel="noopener">${n&&[n," "]}<b>${e.title}</b>${e.meta&&[" ",i`<span class="dim">\xB7 ${e.meta}</span>`]}</a>`}return t==="cards"?i`<div key=${e.key} class=${"card"+(e.acked?" acked":"")} onClick=${e.open} style=${e.open?void 0:"cursor:default"}><div class="top"><b>${e.title}</b>${s}${n}</div>${e.meta&&i`<div class="meta" title=${e.metaText}>${e.meta}</div>`}${e.extra}${e.action&&i`<div class="foot"><span class="footact">${e.action}</span></div>`}</div>`:i`<div key=${e.key} class=${"deckline"+(e.open?" click":"")+(e.acked?" acked":"")} onClick=${e.open}>${n&&[n," "]}<b>${e.title}</b>${s&&[" ",s]}${e.meta&&[" ",i`<span class="dim">\xB7 ${e.meta}</span>`]}${e.action&&[" ",i`<span class="dim">\xB7 </span>`,e.action]}${e.extra}</div>`}var pr=(e,t)=>e>0&&i`<a class="deckmore" href=${"#"+t}>+${e} more \u2192</a>`;function gt(e,t,n,s,r,o){let a=t.slice(0,s),l=a.map(c=>Lo(c,r)),u=a.length?r==="cards"?i`<div class="cards">${l}</div>`:l:i`<div class="empty">none</div>`;return i`<section><h2><a href=${"#"+n}>${e} \u2192</a></h2>${o&&i`<div class="tabhead">${o}</div>`}${u}${pr(t.length-a.length,n)}</section>`}function No(e,t,n,s){let r=t.find(c=>c.number===e.nextNumber)||t[0],o=me(e.numbers,new Map(t.map(c=>[c.number,c.title]))),a=r?"next #"+r.number:"nothing mergeable";if(s==="cards"){let c=d=>{let h=n.get(d.key)||[],p=h.length>0&&h.every($=>$.acked),m=h.length?h.map($=>i`<span class=${"badge "+(Yt[$.kind]||"dim")}>${Ks($.kind)}</span>`):i`<span class=${"badge "+E(d.badge)+B(d.badge.text)} title=${j(d.badge.text)}>${d.badge.text}</span>`,f=`${d.repo} \\xB7 ${d.badge.text}${p?" \\xB7 acked":""}`;return i`<div key=${d.key} class=${"card"+(p?" acked":"")} onClick=${S("pr",d.key)}><div class="top">${dt(d)}${m}</div><div class="meta" title=${f}>${f}</div></div>`};return i`<div key=${e.id} class="deckstack"><div class="dim">${o} \xB7 ${a}</div>${e.readiness&&i`<div class=${e.readiness.allReady?"ok":"dim"}>${e.readiness.text}</div>`}<div class="cards">${t.map(c)}</div></div>`}let l=t.flatMap(c=>(n.get(c.key)||[]).map(d=>i`<span class=${"badge "+(Yt[d.kind]||E(c.badge))+(d.acked?" acked":"")}>#${c.number} ${c.badge.text}</span>`)),u=l.flatMap((c,d)=>d?[" ",c]:[c]);return i`<div key=${e.id} class=${"deckline"+(r?" click":"")} onClick=${r&&S("pr",r.key)}><b>${o}</b> <span class="dim">\xB7 ${a}</span>${l.length>0&&[" \\xB7 ",u]}${e.readiness&&i`<div class=${e.readiness.allReady?"ok":"dim"}>${e.readiness.text}</div>`}</div>`}function Ho(e,t){let n=e.stacks.slice(0,3),s=new Map;for(let o of e.prAttention){let a=s.get(o.key)||[];a.push(o),s.set(o.key,a)}let r=n.length?n.map(o=>No(o,e.prs.filter(a=>a.stackId===o.id).sort((a,l)=>a.position-l.position),s,t)):i`<div class="empty">none</div>`;return i`<section><h2><a href="#prs">PRs \u2192</a></h2>${r}${pr(e.stacks.length-n.length,"prs")}</section>`}function ur({inp:e,drafts:t,focus:n,viewedHere:s,unread:r}){let o=e.view,a=e.inflight.map(d=>({key:d.lane+":"+d.id,title:[d.id.slice(0,8)," ",d.repo||""],worker:d.worker,badge:{text:d.verb,tone:d.verb==="needs-decision"||d.verb==="blocked"?"bad":"dim"},meta:[R(d.note||"",90),d.verbAt&&[" \\xB7 ",v(d.verbAt)," ago"],(d.for||d.claimedBy)&&[" \\xB7 ",st(d.for||d.claimedBy)]],metaText:[U(d.note||""),d.verbAt&&`${J(d.verbAt)} ago`,U(d.for||d.claimedBy||"")].filter(Boolean).join(" \\xB7 "),open:S("dispatch",d.lane+":"+d.id)})),l=e.landed.map(d=>({key:d.key,title:[d.id.slice(0,8)," ",d.repo||"",d.unreported&&[" ",i`<span class="badge warn unreported">unreported</span>`]],badge:{text:d.verb,tone:d.verb==="failed"?"bad":"ok"},meta:[R(d.note||"",90)," \\xB7 ",v(d.at)," ago"],metaText:`${U(d.note||"")} \\xB7 ${J(d.at)} ago`,open:S("dispatch",d.lane+":"+d.id)})),u=e.reports.map(d=>{let h=en(d);return{key:d.key,title:d.title,meta:h.nodes,metaText:h.text,href:C(d.key),acked:!!d.acked}}),c=e.traps.map(({x:d})=>({key:d.trapId,title:"\\u{1FAA4} "+(d.label??`wt:${d.trapId}`),badge:d.requested?{text:"requested",tone:"dim"}:d.starting?{text:d.starting.failedAt?"start failed":"starting",tone:d.starting.failedAt?"bad":"warn"}:{text:d.live?d.harness||"live":"signed off",tone:d.live?"ok":"dim",worker:d.live?d:void 0},meta:[d.repo||""," \\xB7 ",i`<span class="catchn" title="catches">\u{1F99E} ${te(d.totalCatches??0)}</span>`," \\xB7 ",Me(d)],metaText:`${d.repo||""} \\xB7 \\u{1F99E} ${te(d.totalCatches??0)} \\xB7 ${ut(d)}`,action:Y(d),extra:Q(d),open:S("trap",d.trapId)}));return i`<div class="deckgrid"><${lr} cards=${e.decisions} drafts=${t} focus=${n} viewedHere=${s} unread=${r} />${gt("in flight",a,"dispatches",4,o)}${gt("Landed \\xB7 24h",l,"dispatches",8,o)}${gt("reports",u,"reports",8,o)}${gt("traps",c,"traps",8,o,i`<${pt} />`)}${Ho(e,o)}</div>`}function jo(e,t){if(!t)return e;let n=new Map(e.map(o=>[o.id,o])),s=o=>{let a=o,l=new Set;for(;a.followUp&&n.has(a.followUp)&&!l.has(a.id);)l.add(a.id),a=n.get(a.followUp);return a.id},r=new Map;for(let o of e){let a=s(o),l=r.get(a)||[];l.push(o),r.set(a,l)}return[...r.values()].sort((o,a)=>a[0].sort-o[0].sort).flatMap(o=>o.sort((a,l)=>a.id===s(a)?-1:l.id===s(l)?1:a.sort-l.sort))}function Bo(e,t){let n=e.lane+":"+e.id;return i`<tr key=${n} class="rowhead" onClick=${S("dispatch",n)}><td>${t&&e.followUp&&i`<span class="dim">\u21B3 </span>`}${e.id.slice(0,8)}</td><td>${e.lane} / ${e.bucket}</td><td>${e.repo}</td><td class=${"v-"+e.verb}>${e.verb}</td><td class="grow">${R(e.note??"",90)}${at(e)}${Vt(e)}${ot(e)}</td><td>${v(e.verbAt)}</td><td>${Ce(e)}</td><td>${fe(e)}</td></tr>`}function Uo(e){let t=e.lane+":"+e.id;return i`<div key=${t} class="card" onClick=${S("dispatch",t)}><div class="top"><b>${e.id.slice(0,8)}</b>${Vt(e)}<span class=${"badge v-"+e.verb+B(e.verb)} title=${j(e.verb)}>${e.verb}</span></div><div class="meta" title=${`${e.repo} \\xB7 ${e.lane} ${e.bucket}`}>${e.repo} \xB7 ${e.lane} ${e.bucket}${e.verbAt&&[" \\xB7 ",v(e.verbAt)]}</div>${e.note&&i`<div class="note" title=${U(e.note)}>${R(e.note)}</div>`}${at(e)}${ot(e)}<div class="foot">${Ce(e)} ${fe(e)}</div></div>`}function fr({inp:e,more:t}){let n=e.list,s=t&&i`<${ue} kind="dispatches" more=${t} />`;return e.view==="cards"?[n.length?i`<div class="cards">${n.map(Uo)}</div>`:i`<div class="empty">no dispatches match</div>`,s]:[M(["id","lane / bucket","repo","verb","note","age","addressed","pr"],jo(n,e.chain).map(r=>Bo(r,e.chain)),"no dispatches match"),s]}var Wo={deck:"On deck",dispatches:"Dispatches",traps:"Traps",prs:"PRs",reports:"Reports",notices:"Notices",stats:"Stats"},qo=["working","needs-decision","blocked","paused","done","failed","unknown"],mr=(e,t)=>i`<span role="img" aria-label=${t} title=${t}>${e}</span>`;function Fo(e,t){let n=t.daemonStale,s=e.daemon?[i`<span class=${n?"bad":"ok"}>${n&&"stale "}${v(e.daemon.heartbeat)} ago</span>`," ",i`<span class="dim">v${e.daemon.version}</span>`]:i`<span class="bad">down</span>`;return[i`<span class="chip">daemon ${s}</span>`,t.stats&&i`<span class="chip" title="catches today">\u{1F99E} ${t.stats.catchesToday} today</span>`,e.slots&&i`<span class="chip">active ${mr("\\u{1F3A3}","headless")} ${e.slots.headless} of ${e.slots.limit}; ${mr("\\u{1FAA4}","traps")} ${e.slots.traps}${e.slots.parked?`; parked: ${e.slots.parked} (no slot)`:""}</span>`,t.helms.map(({x:r,stale:o})=>i`<span key=${r.grounds} class="chip click" onClick=${S("helm",r.grounds)}>\u26F5 <${H} worker=${r} label=${i`<b>${r.man}</b>`} cls="" /> <span class="dim">helm ${r.grounds}</span> <span class=${o?"warn":"ok"}>${o&&"stale "}${v(r.heartbeatAt)} ago</span></span>`)]}var ln=[];function Ko(e){let t=[...new Set([...e.dispatches.map(n=>n.repo),...e.notices.map(n=>n.repo),...e.prs.map(n=>n.repo)].filter(Boolean))].sort();return t.length!==ln.length&&(ln=t),ln}var dn=[];function Vo(e){let t=[...new Set(e.notices.map(n=>n.kind))].sort();return t.length!==dn.length&&(dn=t),dn}var Ie=e=>e.currentTarget.value;function zo(e,t,n){let s=a=>t===a?"":"display:none",r=e?Ko(e):[],o=e?Vo(e):[];return i`<div class="controls" style=${t==="stats"?"display:none":void 0}>\n <select id="f-lane" style=${e&&s("dispatches")} value=${n.lane} onChange=${a=>N({lane:Ie(a)})}>\n <option value="">all lanes</option>\n <option value="work">work</option>\n <option value="chore">chore</option>\n </select>\n <select id="f-repo" value=${n.repo} onChange=${a=>N({repo:Ie(a)})}>\n <option value="">all repos</option>\n ${r.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <select id="f-verb" style=${e&&s("dispatches")} value=${n.verb} onChange=${a=>N({verb:Ie(a)})}>\n <option value="">all verbs</option>\n ${qo.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <label id="chain-control" style=${e&&s("dispatches")}><input id="f-chain" type="checkbox" checked=${!!n.chain} onChange=${a=>N({chain:a.currentTarget.checked})} /> group by chain</label>\n <select id="f-kind" style=${e&&s("notices")} value=${n.noticeKind} onChange=${a=>N({noticeKind:Ie(a)})}>\n <option value="">all notice kinds</option>\n ${o.map(a=>i`<option key=${a}>${a}</option>`)}\n </select>\n <input id="f-q" type="search" placeholder="search id \xB7 note \xB7 brief" value=${n.q} onInput=${a=>N({q:Ie(a)})} />\n </div>`}function hr({d:e,inp:t,tab:n,st:s,stale:r,unread:o=0}){return[i`<div class="headerline"><h1>\u{1F99E}\u2728 spyglass<span id="stale" style=${e||r?r?"display:inline":"display:none":void 0}> \xB7 STALE FEED</span></h1><span id="settings-slot"><button id="gearbtn" title="settings" aria-label="settings" onClick=${()=>O("settings","browser")}>\u2699</button></span></div>`,i`<div class="chips"><span id="chips" style="display:contents">${e&&t&&Fo(e,t.chips)}</span><span class="chip dim" id="clock">${e&&new Date(e.now).toLocaleTimeString("en-GB")}</span></div>`,i`<nav class="tabs" id="tabs" aria-label="Spyglass views">${se.map(a=>i`<a href=${"#"+a} data-tab=${a} class=${e?a===n?"on":"":void 0}>${Wo[a]}${a==="deck"&&o>0&&i`<span class="dbadge" aria-label=${`${o} new decision${o===1?"":"s"}`}>${o}</span>`}</a>`)}</nav>`,zo(e,n,s)]}var gr=({d:e})=>e&&["\\u{1F99E}\\u2728 lobstah v"+e.version+" \\xB7 ",i`<a href=${e.repoUrl} target="_blank">${e.repoUrl.replace("https://github.com/","")}</a>`];function $r(e,t){if(!t.lobs)return[];let n={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready","stack-ready":"stack ready",landed:"landed",watch:"watch",report:"report"},s=t.hidden??{},r=e.filter(a=>!a.quiet&&!a.acked&&!(a.key!==void 0&&s[a.key]===a.stateHash)).map(a=>{let l=n[a.kind??""]??"",u=a.key!==void 0?{hideKey:a.key,hideHash:a.stateHash??""}:{};return a.kind==="decision"&&a.key?{key:"decision:"+a.key,text:a.note||a.verb,label:l,hash:Tt(a.key),...u}:(a.kind??"question")==="question"&&a.key?{key:"question:"+a.key,text:a.note||a.verb,label:l,hash:Tt(a.key),...u}:a.kind==="report"&&a.key?{key:"report:"+a.key,text:a.note||a.verb,label:l,href:C(a.key),...u}:typeof a.kind=="string"&&(a.kind.startsWith("pr:")||a.kind==="stack-ready")&&a.prUrl?{key:a.kind+":"+(a.key??a.prUrl),text:a.note||a.kind,href:a.prUrl,label:l,...u}:{key:(a.kind??"question")+":"+(a.key??a.lane+":"+a.id),text:a.note||a.verb,label:l,...a.kind==="watch"?{}:{open:{type:"dispatch",key:a.lane+":"+a.id}},...u}});!r.length&&t.preview&&(r=[{key:"preview",text:"attention questions crawl in here",...t.previewHelm?{open:{type:"helm",key:t.previewHelm}}:{}}]);let o=r.length>4?r.length-4:0;return r=r.slice(0,4),o&&(r[3]={...r[3],text:"\\u2026and "+o+" more \\u2014 see attention",label:""}),r}var vr="data:image/png;base64,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";var kr="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAA2UlEQVR4nGNgwAPeHo35D8K45JnwaRQS/YXPbAacmkEa/3z/BaZx2c6Ey1YGIgAjLsV8PF/g7E9feMC0sPUSRhTNuPwGcjI28AlqENzZIIUw/O41G8O58z/BkiycbGDFl278R3GRENQyJpBTkE1DtgFkyIMnn+EGwQDIApA+uB9AzgeZCtIEMhlmu54GI1gMFgafvvDA/Y4SADADYABkG7LfPyFpxIgq9IBD1ojsbAZ0zYTiFlvoY00ksFAGYWw2wtWhC4BD/gsiQUBcxAbxEiI4MAE+p2PLYQAGj4EmRoa2cwAAAABJRU5ErkJggg==";var $t=()=>i`<span class="pet-art" aria-hidden="true"><div class="sprite" style=${{backgroundImage:`url(${vr})`}}></div><img class="star" src=${kr} alt="" /></span>`;function Qo(e,t){let n="animation-duration:"+((innerWidth+180)/(100+t*12)).toFixed(1)+"s;animation-delay:-"+t*9%14+"s",s=()=>{e.hideKey&&ws(e.hideKey,e.hideHash??"")},r=[i`<div class="bub">${e.label&&[i`<span class="badge dim">${e.label}</span>`," "]}<span>${e.text.length>48?e.text.slice(0,47)+"\\u2026":e.text}</span></div>`,i`<${$t} />`],o=e.open;return e.hash?i`<a key=${e.key} class="lob" style=${n} title="open the decision" href=${e.hash} onClick=${s}>${r}</a>`:e.href?i`<a key=${e.key} class="lob" style=${n} title=${e.label==="report"?"open the report":"open the PR"} href=${e.href} target="_blank" rel="noopener" onClick=${s}>${r}</a>`:i`<div\n key=${e.key}\n class="lob"\n style=${n}\n title="click to open"\n onClick=${()=>{s(),o&&O(o.type,o.key)}}\n >\n ${r}\n </div>`}function br({state:e}){let t=e.snapshot,n=$r(t?.attention||[],{lobs:e.prefs.lobs,hidden:e.lobHidden,preview:e.preview,previewHelm:t&&t.helms.length?t.helms[0].grounds:void 0}),s=n.map(r=>r.key).join("|");return Ft(()=>n.map((r,o)=>Qo(r,o)),[s])}function vt({box:e}){if(!e)return null;let t=n=>{n.target===n.currentTarget&&de()};return i`<div id="lightbox" class="lightbox" role="dialog" aria-label=${e.name} onClick=${t}>\n <button type="button" class="lbclose" title="close" onClick=${de}>\xD7</button>\n <img class="lbimg" src=${e.src} alt=${e.name} />\n <a class="lboriginal" href=${e.src} target="_blank" rel="noopener">open original \xB7 ${e.name}</a>\n </div>`}var he=i`<span class="x" onClick=${ce}>\xD7</span>`,yr=(e,t,n)=>i`<span class="seg">${t.map(([s,r])=>i`<button class=${s===n?"on":""} onClick=${()=>e(s)}>${r}</button>`)}</span>`;function Xo(e,t){let n=yr(ys,[["table","table"],["cards","cards"]],t.view),s=yr(_s,[["on","on"],["off","off"]],t.lobs?"on":"off"),r=e.attentionError?e.attentionError:(e.attentionKinds||[]).join(" \\xB7 ");return[he,i`<h3>\u2699 settings <span class="dim" style="font-weight:normal">\xB7 this browser only</span></h3>`,i`<div class="settings"><div class="row"><span class="lbl">view<span class="hint">cards or table (notices stay a table)</span></span>${n}</div><div class="row"><span class="lbl">lobs<span class="hint">crawling lobsters in this page</span></span>${s}</div><div class="row"><span class="lbl">attention<span class="hint">kinds shown \u2014 attentionKinds in config.toml (read-only here)</span></span><span class="dim" style="font-size:11px;text-align:right;max-width:260px">${r}</span></div></div>`]}function Zo(e,t){let n=me(t.numbers,new Map(t.numbers.map((r,o)=>[r,t.titles[o]])),e.number),s=t.nextMergeable?[" \\xB7 ",i`<span class="ok">next mergeable</span>`]:t.blockedBy?" \\xB7 blocked by #"+t.blockedBy:t.nextNumber?" \\xB7 next is #"+t.nextNumber:"";return[n," \\xB7 ",t.position," of ",t.size," \\xB7 floor ",t.floor,s]}var ea=e=>t=>{t.preventDefault(),O("dispatch",e)};function ta(e,t){let n=Zn(e,t),s=n.pr,r=n.stack,o=n.watch,a=ct(s),l=n.chain.length?n.chain.flatMap((c,d)=>[d?" \\u2192 ":"",c.culled?i`<span class="dim">${c.id.slice(0,8)} (culled)</span>`:[i`<a href="#" onClick=${ea(c.modalKey)}>${c.id.slice(0,8)}</a>`," ",i`<span class="dim">${c.verb}</span>`]]):i`<span class="dim">none</span>`,u=o?[i`<div>${o.key} \xB7 owner ${o.owner||"?"} \xB7 ${o.lastCheckedAt?["checked ",v(o.lastCheckedAt)," ago"]:"never checked"}</div>`,o.lastError&&i`<div class="bad">${o.lastError}</div>`,i`<div class="dim" style="font-size:11px;margin-top:4px">cursor</div>`,T(o.cursor)]:i`<div class="dim">no watch \u2014 <code>lobstah watch add ${s.url}</code> registers one</div>`;return[he,i`<h3>${lt(s)} ${s.title||""} <span class=${"badge "+E(s.badge)}>${s.badge.text}</span>${s.draft&&s.badge.text!=="draft"&&[" ",i`<span class="badge pr-draft">draft</span>`]}</h3>`,i`<div class="sub">${s.repo} \xB7 ${s.state} \xB7 observed ${v(s.observedAt)} ago${s.gate&&" \\xB7 gate "+s.gate}</div>`,i`<div class="sec">checks</div><div>${Te(s)}</div><div class="sec">review</div><div>${a||i`<span class="dim">no review yet</span>`}</div><div class="sec">merge</div><div>${Ae(s)}</div>${s.repairWait&&i`<div class="sec">repair waits</div><div>${s.repairWait.heldBy}: ${s.repairWait.reason}${s.repairWait.until?" \\xB7 until "+s.repairWait.until:""}</div>`}<div class="sec">refs</div><div>${s.headRefName||"?"} \u2192 ${s.baseRefName||"?"}</div><div class="sec">stack</div><div>${r?Zo(s,r):i`<span class="dim">not stacked</span>`}</div><div class="sec">dispatch chain</div><div>${l}</div><div class="sec">watch</div>`,u]}function na(e){let t=Date.now()-Date.parse(e.heartbeatAt)>18e5;return[he,i`<h3>\u26F5 ${e.man}</h3><div class="sub">helm of <b>${e.grounds}</b> (${(e.repos||[]).join(", ")})</div><div class="sub">${e.cwd??"?"}${e.host&&" \\xB7 "+e.host}</div><div class="sub">session ${e.sessionId??""} \xB7 signed on ${v(e.signedOnAt)} ago \xB7 heartbeat <span class=${t?"warn":"ok"}>${v(e.heartbeatAt)} ago</span></div>`,i`<${rt} worker=${e} />`,e.sessionId&&[i`<div class="sec">open this session</div>`,zt(e)],e.transcript&&[i`<div class="sec">transcript</div>`,T(e.transcript)]]}function sa(e){return[i`<div class="sec">report \xB7 ${e.title}</div>`,i`<div class="sub">${on(e)} \xB7 <a href=${C(e.key)} target="_blank" rel="noopener">open the report \u2197</a></div>`]}function ra(e,t,n){let s=e.claimedBy&&e.claimedBy.startsWith("wt:")?[i`<div class="sec">worked by trap</div>`,i`<div class="claimedby">claimed by ${it(e.claimedBy.slice(3))}</div>`,T(U(e.claimedBy)),i`<div class="dim" style="font-size:11px">an opted-in interactive session mans this seat \u2014 attach would resume someone\'s live thread. Message it instead: lobstah send ${U(e.claimedBy)} "\u2026"</div>`]:[i`<div class="sec">open this session</div>`,T("lobstah attach "+e.id)];return[he,i`<h3>${e.id.slice(0,8)} <span class=${"badge v-"+e.verb}>${e.verb}</span></h3>`,i`<div class="sub">${e.repo} \xB7 ${e.lane} ${e.bucket} \xB7 ${v(e.verbAt)}${e.for&&[" \\xB7 ",Ce(e)]} ${fe(e)}</div>`,s,e.worker&&i`<${rt} worker=${e.worker} headless=${!e.claimedBy?.startsWith("wt:")} />`,e.worktree&&[i`<div class="sec">worktree${e.worktreeOf?" (reused from "+e.worktreeOf.slice(0,8)+")":""}</div>`,T(e.worktree),e.worktreeKept&&i`<div class="dim" style="font-size:11px">kept: ${e.worktreeKept}</div>`],e.transcript&&[i`<div class="sec">transcript</div>`,T(e.transcript)],t&&sa(t),Fs(e,n)]}function oa(e){let t=Re(e),n=e.requested?[e.repo??""," \\xB7 ",e.harness??""," \\xB7 requested ",v(e.requested.at)," ago from the glass; the helm starts it with man throw --new."]:e.starting?e.starting.failedAt?[e.repo??""," \\xB7 reserved ",v(e.starting.reservedAt)," ago \\xB7 start failed: ",e.starting.reason??"",". Its addressed work stays queued; a session can still redeem the ticket, or `lobstah stow --wt ",e.name??e.trapId,"` withdraws it."]:[e.repo??""," \\xB7 reserved ",v(e.starting.reservedAt)," ago \\xB7 starting: waiting for a session to redeem the ticket (due by ",e.starting.deadline,")"]:e.live?[e.repo??"addressed bait only"," \\xB7 session ",e.sessionId??""," \\xB7 signed on ",v(e.signedOnAt)," ago \\xB7 ",t.listen," \\xB7 heartbeat ",t.hb]:"signed off \\u2014 registration gone; the lifecycle, messages, and catches are the surviving record. Re-soaking the same worktree restores this address.",s=e.notices.length?e.notices.map(a=>i`<div key=${a.seq} class="loglines">${v(a.at)} ago \xB7 <b>${a.kind}</b> \u2014 ${a.text}</div>`):i`<div class="empty">none recorded</div>`,r=e.messages.length?e.messages.map(a=>i`<div key=${a.file} class=${"msg"+(a.from==="helm"?" from-helm":"")}><div class="hdr">from ${a.from} \xB7 ${a.at&&[v(a.at)," ago"]} \xB7 ${a.state==="pending"?i`<span class="warn">pending</span>`:i`<span class="ok">delivered</span>`}</div>${a.text}${a.attachments?.length?pe(a.attachments,l=>Bn(e.trapId,l)):""}</div>`):i`<div class="empty">none</div>`,o=e.catches.length?e.catches.map(a=>i`<div key=${a.lane+":"+a.id} class="catch click" onClick=${S("dispatch",a.lane+":"+a.id)}><div class="hdr"><b>${a.id.slice(0,8)}</b><span class=${"badge v-"+a.verb}>${a.verb}</span><span class="dim">${v(a.verbAt)}</span>${fe(a)}</div>${a.note&&i`<div class="loglines">${R(a.note)}</div>`}</div>`):i`<div class="empty">none yet</div>`;return[he,i`<h3>\u{1FAA4} ${e.label??`wt:${e.trapId}`} <span class="badge">${e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.live?"live":"signed off"}</span></h3>`,i`<${rt} worker=${e} />`,e.worktree&&i`<div class="sub">${e.worktree}</div>`,i`<div class="sub">${n}</div>`,i`<div class="sec">window</div>`,Y(e)??i`<span class="dim">Signed off \u2014 no window</span>`,Q(e),!e.requested&&!e.starting&&(e.sessionId||e.link&&ne(e))&&[i`<div class="sec">open this session</div>`,zt(e),e.sessionId&&i`<div class="dim" style="font-size:11px">as registered at sign-on \u2014 a hookless enlistment may hold a made-up id</div>`],i`<div class="sec">lifecycle (${e.notices.length})</div>`,s,i`<div class="sec">messages (${e.messages.length})</div>`,r,i`<div class="sec">catches (${e.catches.length})</div>`,o]}function _r({snapshot:e,modal:t,prefs:n,detail:s=null}){if(!e||!t)return null;let r=oe(e,t,s);if(!r&&t.type==="dispatch"&&s?.key===t.key)return[he,i`<h3>${t.key.slice(t.key.indexOf(":")+1,t.key.indexOf(":")+9)}</h3>`,i`<div class=${s.error?"bad":"dim"}>${s.error??"loading\\u2026"}</div>`];if(!r)return null;if(t.type==="settings")return Xo(r,n);if(t.type==="pr")return ta(e,t.key);if(t.type==="helm")return na(r);if(t.type==="dispatch"){let o=qn(e,r);return ra(r,o,s)}return oa(r)}var aa=e=>i`<tr key=${e.seq}><td class="dim">${v(e.at)}</td><td>${e.kind}</td><td class="grow">${e.text}</td><td class="dim">${e.repo??""}</td></tr>`,wr=({inp:e,more:t})=>[M(["at","kind","text","repo"],e.list.map(aa),"no notices"),t&&i`<${ue} kind="notices" more=${t} />`];function Sr(e){let t=new Map;for(let n of e.prs){let s=t.get(n.stackId)||[];s.push(n),t.set(n.stackId,s)}return e.stacks.map(n=>({s:n,prs:t.get(n.id)||[]})).filter(n=>n.prs.length)}var Dr=(e,t)=>me(e.numbers,new Map(t.map(n=>[n.number,n.title]))),cn=e=>e.state+(e.draft?" \\xB7 draft":"")+(e.state==="MERGED"&&e.mergedAt?" \\xB7 "+e.mergedAt:"");function xr(e){let t=s=>{let r=String(s??"");return r.length>24?r.slice(0,23)+"\\u2026":r},n=e.watches.map(s=>i`<tr key=${s.key}><td>${s.key}</td><td>${s.owner}</td><td title=${s.cursor}>${t(s.cursor)}</td><td>${s.lastCheckedAt&&v(s.lastCheckedAt)}</td><td>${s.lastError||""}</td></tr>`);return[i`<h2>other watches</h2>`,M(["key","owner","cursor","last check","error"],n,"no other watches")]}function ia(e,t){let n=Sr(e).flatMap(({s,prs:r})=>[i`<tr key=${"stack:"+s.id}><th colspan="8">${Dr(s,r)} \xB7 floor ${s.floor}${s.open?" \\xB7 open":" \\xB7 history"}${s.readiness&&i`<div class=${s.readiness.allReady?"ok":"dim"}>${s.readiness.text}</div>`}</th></tr>`,...r.map(o=>i`<tr key=${o.key} class="rowhead" onClick=${S("pr",o.key)}><td>${lt(o)}</td><td class="grow">${o.title||""}</td><td>${cn(o)}</td><td>${Te(o)}</td><td>${ct(o)}</td><td>${Ae(o)}</td><td>${Qt(o.watch)}</td><td>${o.gate||""}</td></tr>`)]);return[M(["PR","title","state","checks","review","merge","watch","gate"],n,"no PR evidence"),t,xr(e)]}function la(e,t){let n=Sr(e),s=o=>i`<div key=${o.key} class="card" onClick=${S("pr",o.key)}><div class="top">${dt(o)}<span class=${"badge "+E(o.badge)+B(o.badge.text)} title=${j(o.badge.text)}>${o.badge.text}</span></div><div class="meta" title=${`${o.repo} \\xB7 ${cn(o)}`}>${o.repo} \xB7 ${cn(o)} \xB7 ${Ae(o)}</div><div class="foot"><span>${Te(o)}</span><span>${Qt(o.watch)}</span>${o.gate&&i`<span>gate ${o.gate}</span>`}</div></div>`;return[n.length?n.map(({s:o,prs:a})=>i`<${ee} key=${"stack:"+o.id}><h2>${Dr(o,a)} \xB7 floor ${o.floor}${o.open?"":" \\xB7 history"}</h2>${o.readiness&&i`<div class=${o.readiness.allReady?"ok":"dim"}>${o.readiness.text}</div>`}<div class="cards">${a.map(s)}</div><//>`):i`<div class="empty">no PR evidence</div>`,t,xr(e)]}function Gr({inp:e,more:t}){let n=t&&i`<${ue} kind="prs" more=${t} />`;return e.view==="cards"?la(e,n):ia(e,n)}var da=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],ca=5,pn=(e,t,n=t+"es")=>`${e} ${e===1?t:n}`,pa=e=>e.count?`${pn(e.count,"catch")} on ${e.date}`:`No catches on ${e.date}`,Cr=new WeakSet,ua=e=>{!e||Cr.has(e)||(Cr.add(e),e.scrollLeft=e.scrollWidth)},Tr={ArrowUp:-1,ArrowDown:1,ArrowLeft:-7,ArrowRight:7};function fa({page:e,focus:t}){let n=e.weeks.flat(),s=t&&n.some(u=>u.date===t)?t:e.today,r=u=>{let c=n.findIndex(p=>p.date===s),d;if(u.key in Tr)d=c+Tr[u.key];else if(u.key==="Home")d=0;else if(u.key==="End")d=n.length-1;else return;u.preventDefault();let h=n[Math.max(0,Math.min(n.length-1,d))];Nt(h.date),u.currentTarget.querySelector(`[data-date="${h.date}"]`)?.focus()},o=e.weeks.length-1,a=(u,c,d)=>{let h=u[d];if(!h)return i`<td key=${c} class="pad"></td>`;let p=pa(h),m=c<4?" tl":c>o-4?" tr":"";return i`<td\n key=${c}\n role="gridcell"\n class=${`day l${h.level}${d<2?" below":""}${m}`}\n data-date=${h.date}\n data-tip=${p}\n aria-label=${p}\n tabindex=${h.date===s?0:-1}\n onFocus=${()=>Nt(h.date)}\n ></td>`},l=e.months[0]?.week??e.weeks.length;return i`<div class="heat-scroll" ref=${ua}>\n <table class="heatmap" role="grid" aria-label=${`Catches per day, last ${e.weeks.length} weeks`} onKeyDown=${r}>\n <thead aria-hidden="true">\n <tr>\n <td class="wd"></td>\n ${l>0&&i`<td colspan=${l}></td>`}\n ${e.months.map((u,c)=>i`<td key=${u.week} class="month" colspan=${(e.months[c+1]?.week??e.weeks.length)-u.week}><span>${u.label}</span></td>`)}\n </tr>\n </thead>\n <tbody>\n ${da.map((u,c)=>i`<tr key=${u} role="row">\n <td class="wd" aria-hidden="true">${c%2?u:""}</td>\n ${e.weeks.map((d,h)=>a(d,h,c))}\n </tr>`)}\n </tbody>\n </table>\n </div>`}var ma=()=>i`<div class="heat-legend" aria-hidden="true">\n Less ${[0,1,2,3,4].map(e=>i`<span key=${e} class=${"swatch l"+e}></span>`)} More\n </div>`;function ha({page:e}){let t=[["today",e.catchesToday],["this week",e.catchesThisWeek],["total",e.totalCatches]];return i`<div class="stat-tiles">\n ${t.map(([n,s])=>i`<div key=${n} class="stat-tile"><div class="n">${s}</div><div class="dim">${n}</div></div>`)}\n </div>`}function ga({page:e}){let t=e.perTrap.slice(0,ca);if(!t.length)return null;let n=t[0].catches||1;return i`<section class="top-traps">\n <h2>Top traps <span class="dim">\xB7 all time</span></h2>\n <ol>\n ${t.map(s=>i`<li key=${s.name}><span class="name" title=${s.name}>${s.name}</span><span class="bar"><span style=${{width:`${s.catches/n*100}%`}}></span></span><span class="n">${pn(s.catches,"catch")}</span></li>`)}\n </ol>\n </section>`}function Ar({page:e,error:t,focus:n}){return e?i`<div class="stats">\n <${ha} page=${e} />\n ${e.totalCatches===0&&i`<div class="stats-empty"><${$t} /><div><b>No catches yet.</b> <span class="dim">A dispatch that finishes done is a catch; each one lands on its day here.</span></div></div>`}\n <section class="heat">\n <h2>Catches per day</h2>\n <${fa} page=${e} focus=${n} />\n <div class="heat-foot">\n <span class="dim"\n >${e.undated>0?`${pn(e.undated,"earlier catch")} ${e.undated===1?"has":"have"} no recorded day${e.historyFrom?`; daily history starts ${e.historyFrom}`:""}.`:""}</span\n >\n <${ma} />\n </div>\n </section>\n <${ga} page=${e} />\n ${t&&i`<div class="dim">${t}; showing the last numbers read.</div>`}\n </div>`:i`<div class="empty">${t??"loading stats\\u2026"}</div>`}var un=e=>e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??(e.live?"":"signed off"),Rr=e=>e.live||e.starting?"":" dim";function $a(e){let t=Re(e);return i`<tr key=${e.trapId} class=${"rowhead"+Rr(e)} onClick=${S("trap",e.trapId)}><td><b>${e.label??`wt:${e.trapId}`}</b></td><td>${e.repo??"\\u2014"}</td><td class="grow">${e.worktree??""}</td><td>${e.harness&&i`<${H} worker=${e} cls="" />`}</td><td>${(e.sessionId??"").slice(0,8)}</td><td>${Me(e)}${Q(e)}</td><td>${t.listen}</td><td>${t.hb}</td><td>${Zt(e)}</td><td class="catchn" title="catches">\u{1F99E} ${te(e.totalCatches??0)}</td><td>${Y(e)}</td></tr>`}function va(e){let t=Re(e),n=Zt(e),s=`${e.repo??(e.live?"addressed bait only":"history")}${e.sessionId?" \\xB7 session "+e.sessionId.slice(0,8):""}`;return i`<div key=${e.trapId} class=${"card"+Rr(e)} onClick=${S("trap",e.trapId)}><div class="top"><b>\u{1FAA4} ${e.label??`wt:${e.trapId}`}</b>${!e.requested&&!e.starting&&e.harness?i`<${H} worker=${e} />`:i`<span class=${"badge"+B(un(e))} title=${j(un(e))}>${un(e)}</span>`}</div><div class="meta" title=${s}>${s}</div>${e.worktree&&i`<div class="note" title=${e.worktree}>${e.worktree}</div>`}<div class="note" title=${ut(e)}>${Me(e)}</div>${Q(e)}<div class="foot"><span>${t.listen}${e.live&&[" \\xB7 heartbeat ",t.hb]} \xB7 <span class="catchn" title="catches">\u{1F99E} ${te(e.totalCatches??0)}</span>${n&&[" \\xB7 ",n]}</span><span class="footact">${Y(e)}</span></div></div>`}function Mr({inp:e}){let t=e.list.map(s=>s.x),n=i`<div class="tabhead"><${pt} /></div>`;return e.view==="cards"?[n,t.length?i`<div class="cards">${t.map(va)}</div>`:i`<div class="empty">no traps soaking</div>`]:[n,M(["address","repo","worktree","harness","session","now","listening","heartbeat","mail","catches","window"],t.map($a),"no traps soaking")]}function Pr({state:e}){let t=ae(e),n=e.route,s=t?Ze():[],r=t&&Xn(t,{st:e.prefs,modal:e.modal,detail:e.detail},Date.now()),o=u=>({left:e.snapshot?Yn(e.snapshot,e.older,u):0,loading:e.olderLoading===u,error:e.olderError?.kind===u?e.olderError.text:void 0}),a=u=>!r||u!==n?null:u==="deck"?i`<${ur} inp=${r.deck} drafts=${e.drafts} focus=${e.focusDecision} viewedHere=${e.viewedHere} unread=${s.length} />`:u==="dispatches"?i`<${fr} inp=${r.dispatches} more=${o("dispatches")} />`:u==="traps"?i`<${Mr} inp=${r.traps} />`:u==="prs"?i`<${Gr} inp=${r.prs} more=${o("prs")} />`:u==="reports"?i`<${Ys} inp=${r.reports} />`:u==="stats"?i`<${Ar} page=${e.stats} error=${e.statsError} focus=${e.statsFocus} />`:i`<${wr} inp=${r.notices} more=${o("notices")} />`,l=u=>{u.target===u.currentTarget&&ce()};return[i`<${hr} d=${t} inp=${r} tab=${n} st=${e.prefs} stale=${e.stale} unread=${s.length} />`,se.map(u=>i`<main key=${u} id=${"page-"+u} class=${t&&u===n?"tabpage on":"tabpage"}><div id=${u}>${a(u)}</div></main>`),i`<footer id="foot"><${gr} d=${t} /></footer>`,i`<div id="lobs"><${br} state=${e} /></div>`,i`<${vt} box=${e.lightbox} />`,i`<div id="overlay" class=${e.modal&&t?"open":t?"":void 0} onClick=${l}><div class="modal" id="modalbox"><${_r} snapshot=${t} modal=${e.modal} prefs=${e.prefs} detail=${e.detail} /></div></div>`,t&&i`<${dr} open=${e.decisionModal} order=${_e()} drafts=${e.drafts} extensions=${t.answerLimits?.extensions??[]} />`,t&&i`<${cr} unread=${s} dismissed=${e.alertDismissed} />`]}function ka({view:e}){if(e.state==="loading")return i`<main class="reportview"><div class="dim">loading\u2026</div></main>`;if(e.state==="error")return i`<main class="reportview"><div class="bad">${e.error}</div></main>`;let t=e.report;return i`<main class="reportview">\n <h1>${t.title}</h1>\n <${ar} r=${t} text=${e.text!==void 0?{text:e.text}:{error:e.error}} />\n </main>`}function Ir({view:e,box:t}){return[i`<${ka} view=${e} />`,i`<${vt} box=${t} />`]}async function Er(e){let t=encodeURIComponent(e),n,s;try{let r=await fetch(`/report/${t}/meta`);if(!r.ok)return{state:"error",error:`report not found (${r.status})`};s=r.headers?.get("x-lobstah-token")??void 0,n=JSON.parse(await r.text())}catch{return{state:"error",error:"report could not be read"}}try{let r=await fetch(Vn(e)),o=r.ok?{text:await r.text()}:{error:`report not found (${r.status})`};return{state:"ready",report:n,...o,...s?{token:s}:{}}}catch{return{state:"ready",report:n,error:"report could not be read"}}}async function Or(e){if(!(e.state!=="ready"||e.text===void 0||e.report.acked||!e.token))try{await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":e.token},body:JSON.stringify({kind:"report-viewed",payload:{key:e.report.key}})})}catch{}}var ba=3e4,Lr="lobstah-glass-page",Hr="lobstah-glass-shown",ya=20;function _a(){try{let t=sessionStorage.getItem(Lr);if(t&&/^[A-Za-z0-9_-]{8,64}$/.test(t))return t}catch{}let e="";try{e=Array.from(crypto.getRandomValues(new Uint8Array(12)),t=>t.toString(16).padStart(2,"0")).join("")}catch{for(;e.length<24;)e+=Math.random().toString(36).slice(2);e=e.slice(0,24)}try{sessionStorage.setItem(Lr,e)}catch{}return e}var Nr=null,jr=()=>Nr??(Nr=_a()),mn=[];function Br(){try{let e=JSON.parse(sessionStorage.getItem(Hr)??"[]");if(Array.isArray(e))return e.filter(t=>typeof t=="string")}catch{}return mn}function wa(e){mn=[...Br(),e].slice(-ya);try{sessionStorage.setItem(Hr,JSON.stringify(mn))}catch{}}function Sa(e){if(!e||typeof e!="object")return!1;let{id:t,hash:n}=e;if(typeof t!="string"||!t||!Fn(n)||Br().includes(t))return!1;if(wa(t),n==="")return!0;let s=be(n);return s!==null?location.pathname!==C(s)&&location.assign(C(s)):location.pathname!=="/"?location.assign(`/${n}`):location.hash!==n&&(location.hash=n),!0}var fn=!1;async function Ee(){if(!fn){fn=!0;try{let e=document.hidden?"hidden":"visible",t=await fetch(`/api/presence?page=${jr()}&vis=${e}`,{method:"POST",cache:"no-store"});if(!t.ok)return;Sa((await t.json())?.show)}catch{}finally{fn=!1}}}function hn(e){let t=null,n=0,s=()=>{let r=document.hidden?ba:e??0;r!==n&&(t&&clearInterval(t),t=r?setInterval(()=>{Ee()},r):null,n=r)};document.addEventListener("visibilitychange",()=>{s(),Ee()}),window.addEventListener("pagehide",()=>{try{navigator.sendBeacon?.(`/api/presence?page=${jr()}&vis=gone`)}catch{}}),s(),Ee()}var gn=!1,Oe=null,Le=null;function Da(e){let t=e.headers?.get("x-lobstah-beats");if(t)try{return JSON.parse(decodeURIComponent(t))}catch{return}}async function $n(){if(!gn){gn=!0,Ee();try{let e=await fetch("/data",{cache:"no-store",headers:Le?{"if-none-match":Le}:{}});if(e.status===304){let t=Da(e);t?ps(t):Qe(await xa())}else{if(!e.ok)throw new Error(`/data answered ${e.status}`);Le=e.headers?.get("etag")??null,Qe(await e.json())}Lt(),g().route==="stats"&&De()}catch{$s()}finally{gn=!1}}}async function xa(){Le=null;let e=await fetch("/data",{cache:"no-store"});if(!e.ok)throw new Error(`/data answered ${e.status}`);return Le=e.headers?.get("etag")??null,await e.json()}var Ur=()=>{Oe||(Oe=setInterval($n,2e3))},Ga=()=>{Oe&&clearInterval(Oe),Oe=null};function Wr(){document.addEventListener("visibilitychange",()=>{document.hidden?Ga():($n(),Ur())}),$n(),document.hidden||Ur()}var vn=()=>jn(location.hash),qr=e=>window.addEventListener("hashchange",()=>e(vn()));function Kr(){let e=be(location.hash);return e===null?!1:(location.replace(C(e)),!0)}var Vr=()=>({snapshot:void 0,route:vn(),prefs:ns(),modal:null,detail:null,older:Pt,olderLoading:null,olderError:null,stale:!1,lobHidden:rs(),focusResults:{},preview:new URLSearchParams(location.search).has("lob"),drafts:{},focusDecision:re(location.hash),decisionModal:re(location.hash)?{key:re(location.hash)}:null,viewedHere:{},alertDismissed:[],lightbox:null,stats:null,statsError:null,statsFocus:null}),Fr=Kn(location.pathname);Fr!==null?Ca(Fr):Kr()||Ta();function Ca(e){It(Vr());let t={state:"loading"},n=()=>Gt(Z(Ir,{view:t,box:g().lightbox}),document.body);document.title="report \\xB7 lobstah glass",Et(n),n(),hn(2e3),Er(e).then(s=>{t=s,s.state==="ready"&&(document.title=`${s.report.title} \\xB7 lobstah glass`),n(),Or(s)}),document.addEventListener("keydown",s=>{s.key==="Escape"&&g().lightbox&&de()})}function Ta(){It(Vr());let e,t=!1,n=()=>{let a=g(),l=a.route!==e||!t&&!!a.snapshot;Gt(Z(Pr,{state:a}),document.body),e=a.route,t||(t=!!a.snapshot),l&&window.scrollTo(0,0),a.focusDecision||(s=null),r(a.focusDecision)},s=null;function r(a){if(!a||a===s)return;let l=[...document.querySelectorAll("[data-decision]")].find(u=>u.getAttribute("data-decision")===a);l&&(s=a,l.scrollIntoView?.({block:"center"}))}Et(n),n(),qr(a=>{if(Kr())return;let l=re(location.hash);l!==g().focusDecision&&(s=null),k({route:a,focusDecision:l}),l&&ie(l),a==="stats"&&De()});let o=a=>!!a&&(!!a.closest?.("input, textarea, select, [contenteditable]")||a.isContentEditable===!0);document.addEventListener("keydown",a=>{let l=g(),u=a.target;if(a.key==="Escape"){l.lightbox?de():l.decisionModal?o(u)&&u.closest?.(".dmodal")?(u.blur(),document.querySelector(".dmodal")?.focus()):le():ce();return}if(!(a.metaKey||a.ctrlKey||a.altKey||a.isComposing||a.keyCode===229||o(u)||l.lightbox)){if(l.decisionModal){a.key==="ArrowLeft"||a.key==="ArrowRight"?(a.preventDefault(),we(a.key==="ArrowLeft"?-1:1)):/^[1-9]$/.test(a.key)?ls(Number(a.key))&&a.preventDefault():a.key==="Enter"&&u?.matches?.(".dmodal .dopt.on")&&l.decisionModal.key&&(a.preventDefault(),et(l.decisionModal.key));return}a.key==="d"&&!a.shiftKey&&!l.modal&&(a.preventDefault(),ie())}}),hn(),Wr(),g().route==="stats"&&De()}})();</script>\n </body>\n</html>\n';
17333
17406
 
17334
17407
  // apps/cli/src/glass-snapshot-thread.ts
17335
17408
  init_dist2();
@@ -18891,7 +18964,7 @@ function discoverPrStack(ref, opts = {}) {
18891
18964
  }
18892
18965
  }
18893
18966
  }
18894
- const tmp = `${file3}.tmp-${process.pid}`;
18967
+ const tmp = uniqueTempPath(file3);
18895
18968
  fs81.writeFileSync(tmp, JSON.stringify(checked));
18896
18969
  fs81.renameSync(tmp, file3);
18897
18970
  }
@@ -19050,9 +19123,18 @@ function observePr(ref, view, opts = {}) {
19050
19123
  const id = opts.dispatchId;
19051
19124
  const lane = id ? laneOf4(id) : void 0;
19052
19125
  const ev = id && lane ? readEvidence(id, lane) : void 0;
19126
+ const other = ev?.prUrls?.some((u) => parsePrRef(u)?.key === ref.key) && parsePrRef(ev.prUrl ?? "")?.key !== ref.key;
19127
+ const current = view.fetchedAt ? readPr(ref.key) : void 0;
19128
+ if (current && Date.parse(current.observedAt) >= Date.parse(pr.observedAt)) {
19129
+ if (id && lane && !current.dispatches.includes(id)) {
19130
+ const { after: after2 } = upsertPr(current, id);
19131
+ if (!other) mergeEvidence(id, lane, { pr: after2 });
19132
+ return after2;
19133
+ }
19134
+ return current;
19135
+ }
19053
19136
  const legacyBefore = ev?.pr && parsePrRef(ev.pr.url)?.key === ref.key ? ev.pr : void 0;
19054
19137
  const { before, after } = upsertPr(pr, lane ? id : void 0);
19055
- const other = ev?.prUrls?.some((u) => parsePrRef(u)?.key === ref.key) && parsePrRef(ev.prUrl ?? "")?.key !== ref.key;
19056
19138
  if (id && lane && !other) mergeEvidence(id, lane, { pr });
19057
19139
  const was = before?.state ?? legacyBefore?.state;
19058
19140
  const terminal3 = pr.state === "MERGED" || pr.state === "CLOSED";
@@ -19327,7 +19409,7 @@ init_dist3();
19327
19409
  init_dist2();
19328
19410
  import { execFile as execFile4 } from "node:child_process";
19329
19411
  import { promisify as promisify4 } from "node:util";
19330
- import { randomUUID as randomUUID7 } from "node:crypto";
19412
+ import { randomUUID as randomUUID8 } from "node:crypto";
19331
19413
  function launchShellText(launch) {
19332
19414
  const env = Object.entries(launch.env).map(([k, v]) => `${k}=${shellQuote(v)}`);
19333
19415
  return [`cd ${shellQuote(launch.cwd)} &&`, ...env, ...launch.argv.map(shellQuote)].join(" ");
@@ -19545,7 +19627,7 @@ async function throwNew(opts) {
19545
19627
  });
19546
19628
  }
19547
19629
  async function throwBatch(opts) {
19548
- const batch = opts.batch ?? randomUUID7();
19630
+ const batch = opts.batch ?? randomUUID8();
19549
19631
  const each = { ...opts, batch };
19550
19632
  const jobs = [];
19551
19633
  if ("rows" in opts) {
@@ -20981,7 +21063,7 @@ ${usageFor(cmd)}`);
20981
21063
  throw new Error("dispatch requires --repo (or --pool) and --brief <file> (or --brief-text)");
20982
21064
  }
20983
21065
  const d = {
20984
- id: opt("--id") ?? randomUUID8(),
21066
+ id: opt("--id") ?? randomUUID9(),
20985
21067
  repo,
20986
21068
  brief: briefText ?? fs91.readFileSync(briefFile, "utf8"),
20987
21069
  harness: opt("--harness"),
@@ -21211,7 +21293,7 @@ ${[text, block].filter(Boolean).join("\n\n")}`,
21211
21293
  if (trap && Date.now() - (Date.parse(trap.heartbeatAt) || 0) < loadConfig().soak.ttlSecs * 1e3) address = claimedBy;
21212
21294
  else headless = true;
21213
21295
  const followUp = {
21214
- id: randomUUID8(),
21296
+ id: randomUUID9(),
21215
21297
  repo: origin.descriptor.repo,
21216
21298
  brief: `Follow-up instruction from ${from} on dispatch ${origin.id}:
21217
21299
  ${text}`,