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.
- package/dist/main.js +189 -107
- package/dist/runner.js +13 -8
- 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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
2125
|
-
|
|
2126
|
-
|
|
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
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
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
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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
|
-
|
|
2594
|
-
|
|
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:
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 ??
|
|
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 = () =>
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 ??
|
|
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") ??
|
|
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:
|
|
21296
|
+
id: randomUUID9(),
|
|
21215
21297
|
repo: origin.descriptor.repo,
|
|
21216
21298
|
brief: `Follow-up instruction from ${from} on dispatch ${origin.id}:
|
|
21217
21299
|
${text}`,
|