lobstah 0.6.1 → 0.6.2
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 +68 -7
- package/docs/harness/claude-code.md +2 -0
- package/docs/harness/codex.md +4 -3
- package/docs/man.md +18 -7
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2376,9 +2376,36 @@ function validSessionLink(value) {
|
|
|
2376
2376
|
return false;
|
|
2377
2377
|
return /^claude:\/\/claude\.ai\/[A-Za-z0-9_/-]+$/.test(value) || /^vscode:\/\/anthropic\.claude-code\/open\?session=[A-Za-z0-9_-]+$/.test(value) || /^codex:\/\/threads\/[A-Za-z0-9-]+$/.test(value);
|
|
2378
2378
|
}
|
|
2379
|
+
function linkMismatch(link, win) {
|
|
2380
|
+
if (!win)
|
|
2381
|
+
return void 0;
|
|
2382
|
+
const ep = win.entrypoint;
|
|
2383
|
+
const bundle = win.bundleId;
|
|
2384
|
+
if (link.startsWith("vscode://")) {
|
|
2385
|
+
if (ep !== void 0)
|
|
2386
|
+
return ep === "claude-vscode" ? void 0 : `a vscode:// link needs the VS Code extension; this session's entrypoint is ${ep}`;
|
|
2387
|
+
return bundle === void 0 || VSCODE_BUNDLE_RE.test(bundle) ? void 0 : `a vscode:// link needs the VS Code extension; this session runs in ${bundle}`;
|
|
2388
|
+
}
|
|
2389
|
+
if (link.startsWith("claude://")) {
|
|
2390
|
+
if (ep !== void 0) {
|
|
2391
|
+
return ep === "cli" || ep === "claude-vscode" || ep.startsWith("sdk-") ? `a claude:// link needs the Claude desktop app's Code tab; this session's entrypoint is ${ep}` : void 0;
|
|
2392
|
+
}
|
|
2393
|
+
if (bundle !== void 0 && bundle !== CLAUDE_DESKTOP_BUNDLE)
|
|
2394
|
+
return `a claude:// link needs the Claude desktop app; this session runs in ${bundle}`;
|
|
2395
|
+
return win.termProgram === "claude-desktop" ? "a claude:// link needs the Code tab; this session runs in the Claude desktop app's terminal" : void 0;
|
|
2396
|
+
}
|
|
2397
|
+
if (link.startsWith("codex://")) {
|
|
2398
|
+
return bundle === void 0 || bundle === CODEX_BUNDLE ? void 0 : `a codex:// link needs the Codex app; this session runs in ${bundle}`;
|
|
2399
|
+
}
|
|
2400
|
+
return void 0;
|
|
2401
|
+
}
|
|
2402
|
+
var VSCODE_BUNDLE_RE, CLAUDE_DESKTOP_BUNDLE, CODEX_BUNDLE;
|
|
2379
2403
|
var init_session_link = __esm({
|
|
2380
2404
|
"packages/core/dist/session-link.js"() {
|
|
2381
2405
|
"use strict";
|
|
2406
|
+
VSCODE_BUNDLE_RE = /(?:VSCode|Cursor|windsurf)/;
|
|
2407
|
+
CLAUDE_DESKTOP_BUNDLE = "com.anthropic.claudefordesktop";
|
|
2408
|
+
CODEX_BUNDLE = "com.openai.codex";
|
|
2382
2409
|
}
|
|
2383
2410
|
});
|
|
2384
2411
|
|
|
@@ -3753,6 +3780,8 @@ function signOnTrap(opts) {
|
|
|
3753
3780
|
writeTrapAnchor(opts.worktree, { ...anchor, name });
|
|
3754
3781
|
const iso = new Date(now2).toISOString();
|
|
3755
3782
|
const sameSession = prior?.sessionId === opts.sessionId;
|
|
3783
|
+
const window = opts.window ?? (sameSession ? prior.window : void 0);
|
|
3784
|
+
const link = opts.link ?? (sameSession && validSessionLink(prior?.link) ? prior.link : void 0);
|
|
3756
3785
|
const reg = {
|
|
3757
3786
|
trapId,
|
|
3758
3787
|
name,
|
|
@@ -3765,8 +3794,8 @@ function signOnTrap(opts) {
|
|
|
3765
3794
|
signedOnAt: sameSession ? prior.signedOnAt : iso,
|
|
3766
3795
|
heartbeatAt: iso,
|
|
3767
3796
|
firstParkedAt: sameSession ? prior.firstParkedAt : void 0,
|
|
3768
|
-
window
|
|
3769
|
-
link:
|
|
3797
|
+
window,
|
|
3798
|
+
link: link !== void 0 && linkMismatch(link, window) === void 0 ? link : void 0,
|
|
3770
3799
|
claimed: prior?.claimed,
|
|
3771
3800
|
...createdWorktree ? { createdWorktree } : {}
|
|
3772
3801
|
};
|
|
@@ -4510,6 +4539,7 @@ function captureWindow(env = process.env) {
|
|
|
4510
4539
|
tmuxPane: env.TMUX_PANE,
|
|
4511
4540
|
kittyWindow: env.KITTY_WINDOW_ID,
|
|
4512
4541
|
weztermPane: env.WEZTERM_PANE,
|
|
4542
|
+
entrypoint: env.CLAUDE_CODE_ENTRYPOINT,
|
|
4513
4543
|
tty: ancestorTty()
|
|
4514
4544
|
};
|
|
4515
4545
|
for (const k of Object.keys(ref)) {
|
|
@@ -13240,7 +13270,7 @@ import { randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual2 } from
|
|
|
13240
13270
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
13241
13271
|
|
|
13242
13272
|
// apps/cli/src/glass-page.generated.ts
|
|
13243
|
-
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;--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}*{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}.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)}.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}.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}#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:10;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 .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 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}.lob .sprite{width:72px;height:56px;background:url(/lob-sprite.png) 0 0 no-repeat;background-size:400% 100%;image-rendering:pixelated;animation:step 0.5s steps(4) infinite}.lob .fallback{display:inline-block;animation:waddle 0.45s ease-in-out infinite alternate}.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}.lob .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}}@keyframes waddle{from{transform:rotate(-8deg) translateY(0)}to{transform:rotate(8deg) translateY(-3px)}}#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}.dcards{display:flex;flex-direction:column;gap:10px}.dcard{width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.dcard.focus{border-color:var(--link)}.dcard.answered{opacity:0.7}.dcard .dtop{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2)}.dcard .dtop .badge{margin-top:0}.dcard .dtitle{white-space:pre-wrap;overflow-wrap:anywhere}.dcard .dmeta{font-size:11px;margin-left:auto}.dcard .dlink{color:var(--link)}.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}.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;overflow-x:auto;white-space:pre}.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{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}.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}</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 Ae,b,Bt,jn,B,Nt,Ut,Ft,Xe,Te,oe,qt,Ze,Je,Qe,Bn,Se={},Ce=[],Un=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Re=Array.isArray;function P(e,t){for(var s in t)e[s]=t[s];return e}function Ye(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function ae(e,t,s){var n,r,i,o={};for(i in t)i=="key"?n=t[i]:i=="ref"?r=t[i]:o[i]=t[i];if(arguments.length>2&&(o.children=arguments.length>3?Ae.call(arguments,2):s),typeof e=="function"&&e.defaultProps!=null)for(i in e.defaultProps)o[i]===void 0&&(o[i]=e.defaultProps[i]);return xe(e,o,n,r,null)}function xe(e,t,s,n,r){var i={type:e,props:t,key:s,ref:n,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++Bt,__i:-1,__u:0};return r==null&&b.vnode!=null&&b.vnode(i),i}function J(e){return e.children}function Ge(e,t){this.props=e,this.context=t}function W(e,t){if(t==null)return e.__?W(e.__,e.__i+1):null;for(var s;t<e.__k.length;t++)if((s=e.__k[t])!=null&&s.__e!=null)return s.__e;return typeof e.type=="function"?W(e):null}function Fn(e){if(e.__P&&e.__d){var t=e.__v,s=t.__e,n=[],r=[],i=P({},t);i.__v=t.__v+1,b.vnode&&b.vnode(i),et(e.__P,i,t,e.__n,e.__P.namespaceURI,32&t.__u?[s]:null,n,s??W(t),!!(32&t.__u),r),i.__v=t.__v,i.__.__k[i.__i]=i,Xt(n,i,r),t.__e=t.__=null,i.__e!=s&&Wt(i)}}function Wt(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}),Wt(e)}function Ht(e){(!e.__d&&(e.__d=!0)&&B.push(e)&&!De.__r++||Nt!=b.debounceRendering)&&((Nt=b.debounceRendering)||Ut)(De)}function De(){try{for(var e,t=1;B.length;)B.length>t&&B.sort(Ft),e=B.shift(),t=B.length,Fn(e)}finally{B.length=De.__r=0}}function Vt(e,t,s,n,r,i,o,c,u,l,f){var h,d,m,p,g,x,T=n&&n.__k||Ce,$=t.length;for(u=qn(s,t,T,u,$),h=0;h<$;h++)(m=s.__k[h])!=null&&(d=m.__i!=-1&&T[m.__i]||Se,m.__i=h,x=et(e,m,d,r,i,o,c,u,l,f),p=m.__e,m.ref&&d.ref!=m.ref&&(d.ref&&tt(d.ref,null,m),f.push(m.ref,m.__c||p,m)),g==null&&p!=null&&(g=p),4&m.__u?(u=Kt(m,u,e),d.__e&&(d.__e=null)):typeof m.type=="function"&&x!==void 0?u=x:p&&(u=p.nextSibling),m.__u&=-7);return s.__e=g,u}function qn(e,t,s,n,r){var i,o,c,u,l,f=s.length,h=f,d=0;for(e.__k=new Array(r),i=0;i<r;i++)(o=t[i])!=null&&typeof o!="boolean"&&typeof o!="function"?(typeof o=="string"||typeof o=="number"||typeof o=="bigint"||o.constructor==String?o=e.__k[i]=xe(null,o,null,null,null):Re(o)?o=e.__k[i]=xe(J,{children:o},null,null,null):o.constructor===void 0&&o.__b>0?o=e.__k[i]=xe(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):e.__k[i]=o,u=i+d,o.__=e,o.__b=e.__b+1,c=null,(l=o.__i=Wn(o,s,u,h))!=-1&&(h--,(c=s[l])&&(c.__u|=2)),c==null||c.__v==null?(l==-1&&(r>f?d--:r<f&&d++),typeof o.type!="function"&&(o.__u|=4)):l!=u&&(l==u-1?d--:l==u+1?d++:(l>u?d--:d++,o.__u|=4))):e.__k[i]=null;if(h)for(i=0;i<f;i++)(c=s[i])!=null&&(2&c.__u)==0&&(c.__e==n&&(n=W(c)),Qt(c,c));return n}function Kt(e,t,s){var n,r;if(typeof e.type=="function"){for(n=e.__k,r=0;n&&r<n.length;r++)n[r]&&(n[r].__=e,t=Kt(n[r],t,s));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=W(e)),t=s.insertBefore(e.__e,t||null));do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function Wn(e,t,s,n){var r,i,o,c=e.key,u=e.type,l=t[s],f=l!=null&&(2&l.__u)==0;if(l===null&&c==null||f&&c==l.key&&u==l.type)return s;if(n>(f?1:0)){for(r=s-1,i=s+1;r>=0||i<t.length;)if((l=t[o=r>=0?r--:i++])!=null&&(2&l.__u)==0&&c==l.key&&u==l.type)return o}return-1}function Ot(e,t,s){t[0]=="-"?e.setProperty(t,s??""):e[t]=s==null?"":typeof s!="number"||Un.test(t)?s:s+"px"}function we(e,t,s,n,r){var i,o;e:if(t=="style")if(typeof s=="string")e.style.cssText=s;else{if(typeof n=="string"&&(e.style.cssText=n=""),n)for(t in n)s&&t in s||Ot(e.style,t,"");if(s)for(t in s)n&&s[t]==n[t]||Ot(e.style,t,s[t])}else if(t[0]=="o"&&t[1]=="n")i=t!=(t=t.replace(qt,"$1")),o=t.toLowerCase(),t=o in e||t=="onFocusOut"||t=="onFocusIn"?o.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=s,s?n?s[oe]=n[oe]:(s[oe]=Ze,e.addEventListener(t,i?Qe:Je,i)):e.removeEventListener(t,i?Qe:Je,i);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]=s??"";break e}catch{}typeof s=="function"||(s==null||s===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&s==1?"":s))}}function jt(e){return function(t){if(this.l){var s=this.l[t.type+e];if(t[Te]==null)t[Te]=Ze++;else if(t[Te]<s[oe])return;return s(b.event?b.event(t):t)}}}function et(e,t,s,n,r,i,o,c,u,l){var f,h,d,m,p,g,x,T,$,I,re,q,ie,Lt,ye,ze,M=t.type;if(t.constructor!==void 0)return null;128&s.__u&&(u=!!(32&s.__u),i=[c=t.__e=s.__e]),(f=b.__b)&&f(t);e:if(typeof M=="function"){h=o.length;try{if($=t.props,I=M.prototype&&M.prototype.render,re=(f=M.contextType)&&n[f.__c],q=f?re?re.props.value:f.__:n,s.__c?T=(d=t.__c=s.__c).__=d.__E:(I?t.__c=d=new M($,q):(t.__c=d=new Ge($,q),d.constructor=M,d.render=Kn),re&&re.sub(d),d.state||(d.state={}),d.__n=n,m=d.__d=!0,d.__h=[],d._sb=[]),I&&d.__s==null&&(d.__s=d.state),I&&M.getDerivedStateFromProps!=null&&(d.__s==d.state&&(d.__s=P({},d.__s)),P(d.__s,M.getDerivedStateFromProps($,d.__s))),p=d.props,g=d.state,d.__v=t,m)I&&M.getDerivedStateFromProps==null&&d.componentWillMount!=null&&d.componentWillMount(),I&&d.componentDidMount!=null&&d.__h.push(d.componentDidMount);else{if(I&&M.getDerivedStateFromProps==null&&$!==p&&d.componentWillReceiveProps!=null&&d.componentWillReceiveProps($,q),t.__v==s.__v||!d.__e&&d.shouldComponentUpdate!=null&&d.shouldComponentUpdate($,d.__s,q)===!1){t.__v!=s.__v&&(d.props=$,d.state=d.__s,d.__d=!1),t.__e=s.__e,t.__k=s.__k,t.__k.some(function(X){X&&(X.__=t)}),Ce.push.apply(d.__h,d._sb),d._sb=[],d.__h.length&&o.push(d),c=W(s);break e}d.componentWillUpdate!=null&&d.componentWillUpdate($,d.__s,q),I&&d.componentDidUpdate!=null&&d.__h.push(function(){d.componentDidUpdate(p,g,x)})}if(d.context=q,d.props=$,d.__P=e,d.__e=!1,ie=b.__r,Lt=0,I)d.state=d.__s,d.__d=!1,ie&&ie(t),f=d.render(d.props,d.state,d.context),Ce.push.apply(d.__h,d._sb),d._sb=[];else do d.__d=!1,ie&&ie(t),f=d.render(d.props,d.state,d.context),d.state=d.__s;while(d.__d&&++Lt<25);d.state=d.__s,d.getChildContext!=null&&(n=P(P({},n),d.getChildContext())),I&&!m&&d.getSnapshotBeforeUpdate!=null&&(x=d.getSnapshotBeforeUpdate(p,g)),ye=f!=null&&f.type===J&&f.key==null?Jt(f.props.children):f,c=Vt(e,Re(ye)?ye:[ye],t,s,n,r,i,o,c,u,l),d.base=t.__e,t.__u&=-161,d.__h.length&&o.push(d),T&&(d.__E=d.__=null)}catch(X){if(o.length=h,t.__v=null,u||i!=null){if(X.then){for(t.__u|=u?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;i!=null&&(i[i.indexOf(c)]=null),t.__e=c}else if(i!=null)for(ze=i.length;ze--;)Ye(i[ze])}else t.__e=s.__e;t.__k==null&&(t.__k=s.__k||[]),X.then||zt(t),b.__e(X,t,s)}}else i==null&&t.__v==s.__v?(t.__k=s.__k,t.__e=s.__e):c=t.__e=Vn(s.__e,t,s,n,r,i,o,u,l);return(f=b.diffed)&&f(t),128&t.__u?void 0:c}function zt(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(zt))}function Xt(e,t,s){for(var n=0;n<s.length;n++)tt(s[n],s[++n],s[++n]);b.__c&&b.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(i){i.call(r)})}catch(i){b.__e(i,r.__v)}})}function Jt(e){return typeof e!="object"||e==null||e.__b>0?e:Re(e)?e.map(Jt):e.constructor!==void 0?null:P({},e)}function Vn(e,t,s,n,r,i,o,c,u){var l,f,h,d,m,p,g,x=s.props||Se,T=t.props,$=t.type;if($=="svg"?r="http://www.w3.org/2000/svg":$=="math"?r="http://www.w3.org/1998/Math/MathML":r||(r="http://www.w3.org/1999/xhtml"),i!=null){for(l=0;l<i.length;l++)if((m=i[l])&&"setAttribute"in m==!!$&&($?m.localName==$:m.nodeType==3)){e=m,i[l]=null;break}}if(e==null){if($==null)return document.createTextNode(T);e=document.createElementNS(r,$,T.is&&T),c&&(b.__m&&b.__m(t,i),c=!1),i=null}if($==null)x===T||c&&e.data==T||(e.data=T);else{if(i=$=="textarea"&&T.defaultValue!=null?null:i&&Ae.call(e.childNodes),!c&&i!=null)for(x={},l=0;l<e.attributes.length;l++)x[(m=e.attributes[l]).name]=m.value;for(l in x)m=x[l],l=="dangerouslySetInnerHTML"?h=m:l=="children"||l in T||l=="value"&&"defaultValue"in T||l=="checked"&&"defaultChecked"in T||we(e,l,null,m,r);for(l in T)m=T[l],l=="children"?d=m:l=="dangerouslySetInnerHTML"?f=m:l=="value"?p=m:l=="checked"?g=m:c&&typeof m!="function"||x[l]===m||we(e,l,m,x[l],r);if(f)c||h&&(f.__html==h.__html||f.__html==e.innerHTML)||(e.innerHTML=f.__html),t.__k=[];else if(h&&(e.innerHTML=""),Vt(t.type=="template"?e.content:e,Re(d)?d:[d],t,s,n,$=="foreignObject"?"http://www.w3.org/1999/xhtml":r,i,o,i?i[0]:s.__k&&W(s,0),c,u),i!=null)for(l=i.length;l--;)Ye(i[l]);c&&$!="textarea"||(l="value",$=="progress"&&p==null?e.removeAttribute("value"):p!=null&&(p!==e[l]||$=="progress"&&!p||$=="option"&&p!=x[l])&&we(e,l,p,x[l],r),l="checked",g!=null&&g!=e[l]&&we(e,l,g,x[l],r))}return e}function tt(e,t,s){try{if(typeof e=="function"){var n=typeof e.__u=="function";n&&e.__u(),n&&t==null||(e.__u=e(t))}else e.current=t}catch(r){b.__e(r,s)}}function Qt(e,t,s){var n,r;if(b.unmount&&b.unmount(e),(n=e.ref)&&(n.current&&n.current!=e.__e||tt(n,null,t)),(n=e.__c)!=null){if(n.componentWillUnmount)try{n.componentWillUnmount()}catch(i){b.__e(i,t)}n.base=n.__P=n.__n=null}if(n=e.__k)for(r=0;r<n.length;r++)n[r]&&Qt(n[r],t,s||typeof e.type!="function");s||Ye(e.__e),e.__c=e.__=e.__e=void 0}function Kn(e,t,s){return this.constructor(e,s)}function Zt(e,t,s){var n,r,i,o;t==document&&(t=document.documentElement),b.__&&b.__(e,t),r=(n=typeof s=="function")?null:s&&s.__k||t.__k,i=[],o=[],et(t,e=(!n&&s||t).__k=ae(J,null,[e]),r||Se,Se,t.namespaceURI,!n&&s?[s]:r?null:t.firstChild?Ae.call(t.childNodes):null,i,!n&&s?s:r?r.__e:t.firstChild,n,o),Xt(i,e,o),e.props.children=null}Ae=Ce.slice,b={__e:function(e,t,s,n){for(var r,i,o;t=t.__;)if((r=t.__c)&&!r.__)try{if((i=r.constructor)&&i.getDerivedStateFromError!=null&&(r.setState(i.getDerivedStateFromError(e)),o=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,n||{}),o=r.__d),o)return r.__E=r}catch(c){e=c}throw e}},Bt=0,jn=function(e){return e!=null&&e.constructor===void 0},Ge.prototype.setState=function(e,t){var s;s=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=P({},this.state),typeof e=="function"&&(e=e(P({},s),this.props)),e&&P(s,e),e!=null&&this.__v&&(t&&this._sb.push(t),Ht(this))},Ge.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),Ht(this))},Ge.prototype.render=J,B=[],Ut=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Ft=function(e,t){return e.__v.__b-t.__v.__b},De.__r=0,Xe=Math.random().toString(8),Te="__d"+Xe,oe="__a"+Xe,qt=/(PointerCapture)$|Capture$/i,Ze=0,Je=jt(!1),Qe=jt(!0),Bn=0;function zn(e){return{id:e,lane:"work",bucket:"done",repo:"",brief:"",attachments:[],messageAttachments:[],verb:"unknown",log:[],inbox:[],sort:0}}var Yt=new WeakMap;function st(e,t){let s=e.dispatches||[],n=Yt.get(s);return n||Yt.set(s,n=new Map(s.map(r=>[r.id,r]))),{...t,catches:(t.catches||[]).map(r=>n.get(r)??zn(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 le=["deck","dispatches","traps","prs","reports","notices"];function ns(e){let t=String(e||"").replace(/^#/,"");return le.includes(t)?t:"deck"}function ce(e){let t=/^report:(work|chore):(.+)$/.exec(e);return t?{type:"dispatch",key:`${t[1]}:${t[2]}`}:{type:"report",key:e}}function rs(e){let t=/^#?report\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return ce(decodeURIComponent(t[1]))}catch{return null}}var is=e=>`#decision/${encodeURIComponent(e)}`;function nt(e){let t=/^#?decision\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var rt=(e,t,s)=>`/attachment/dispatch/${encodeURIComponent(e)}/${encodeURIComponent(t)}/${encodeURIComponent(s)}`,os=(e,t)=>`/attachment/trap/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,as=e=>/\\.(png|jpe?g|gif|webp)$/i.test(e),it=(e,t)=>`/decision/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function ot(e,t){let s=new Map(t.map(r=>[r.key,r])),n=[];for(let r of e)if(r.kind==="decision"){let i=s.get(r.key);if(!i)continue;n.push({kind:"decision",key:i.key,title:i.title,detail:i.detail,options:i.options,attachments:i.attachments,...i.dispatch?{dispatch:i.dispatch,lane:i.lane??"work"}:{},...i.repo?{repo:i.repo}:{},at:i.askedAt})}else r.kind==="question"&&n.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??""});return n.sort((r,i)=>i.at.localeCompare(r.at)||r.key.localeCompare(i.key))}function ls(e){let t=(e.text??"").split(`\n`).map(s=>s.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 cs(e,t){return(e.reports||[]).find(s=>s.key===`report:${t.lane}:${t.id}`)}function de(e){return e.author==="helm"?"":e.trap?e.trap:e.author==="headless"?e.dispatch?e.dispatch.slice(0,8):"":e.author}var es=(e,t)=>+!!e.acked-+!!t.acked||t.filedAt.localeCompare(e.filedAt),ds=e=>`/report/${encodeURIComponent(e)}/md`,at=(e,t)=>`/report/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function ts(e,t,s){return!!e&&s-Date.parse(e)>t}function ss(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 s=t.q.toLowerCase();if(!(e.id+" "+(e.note||"")+" "+(e.brief||"")+" "+(e.repo||"")+" "+(e.for||"")).toLowerCase().includes(s))return!1}return!0}function Q(e,t){if(!t)return null;if(t.type==="helm")return e.helms.find(n=>n.grounds===t.key)||null;if(t.type==="dispatch")return e.dispatches.find(n=>n.lane+":"+n.id===t.key)||null;if(t.type==="pr")return(e.prs||[]).find(n=>n.key===t.key)||null;if(t.type==="report")return(e.reports||[]).find(n=>n.key===t.key)||null;if(t.type==="settings")return{attentionKinds:e.attentionKinds||[],attentionError:e.attentionError};let s=e.traps.find(n=>n.trapId===t.key);return s?st(e,s):null}function ps(e,t,s){let n=t.st,r=String(n.q||"").toLowerCase(),i=(...p)=>!r||p.join(" ").toLowerCase().includes(r),o=p=>({x:p,stale:ts(p.heartbeatAt,18e5,s)}),c=Q(e,t.modal),u=(p,g)=>!!p&&s-Date.parse(p)<=g,l=p=>Math.max(0,...(p.notices||[]).filter(g=>g.kind==="trap-stowed"||g.kind==="trap-ghosted").map(g=>Date.parse(g.at)||0)),f=p=>p.live||!!p.starting||!!p.requested,h=[...e.traps||[]].sort((p,g)=>Number(f(g))-Number(f(p))||Number(g.live)-Number(p.live)||(p.live?(Date.parse(p.signedOnAt||"")||0)-(Date.parse(g.signedOnAt||"")||0):l(g)-l(p))||(p.name??p.trapId).localeCompare(g.name??g.trapId)),d=h.filter(p=>(f(p)||(p.notices||[]).some(g=>(g.kind==="trap-stowed"||g.kind==="trap-ghosted")&&u(g.at,36e5)))&&i(p.name,p.trapId,p.repo,p.worktree)),m=({ageSecs:p,...g})=>g;return{chips:{daemon:e.daemon,daemonStale:!!e.daemon&&ts(e.daemon.heartbeat,9e4,s),helms:e.helms.map(o)},deck:{view:n.view,decisions:ot(e.attention||[],e.decisions||[]).filter(p=>p.kind==="decision"?i(p.kind,p.repo,p.title,p.dispatch,p.detail):i(p.kind,p.repo,p.note,p.dispatch)),prAttention:(e.attention||[]).filter(p=>p.kind&&p.kind.startsWith("pr:")).map(m),landed:(e.landed||[]).filter(p=>u(p.at,864e5)&&i(p.repo,p.note,p.id)).sort((p,g)=>Date.parse(g.at)-Date.parse(p.at)).slice(0,8),reports:(e.reports||[]).filter(p=>i(p.title,p.author,p.dispatch,p.repo)).sort(es),inflight:e.dispatches.filter(p=>p.bucket!=="done"&&ss(p,{...n,lane:"",repo:"",verb:""})),traps:d.map(p=>o(st(e,p))),stacks:(e.stacks||[]).filter(p=>p.open&&i(p.repo,p.numbers.join(" "))),prs:(e.prs||[]).filter(p=>p.state==="OPEN"),error:e.attentionError},dispatches:{view:n.view,chain:n.chain,list:e.dispatches.filter(p=>ss(p,n))},traps:{view:n.view,list:h.filter(p=>(!n.repo||p.repo===n.repo)&&i(p.name,p.trapId,p.repo,p.worktree,p.harness)).map(p=>o(st(e,p)))},prs:{view:n.view,stacks:(e.stacks||[]).filter(p=>!n.repo||p.repo===n.repo),prs:(e.prs||[]).filter(p=>(!n.repo||p.repo===n.repo)&&i(p.number,p.title,p.url,p.state,p.baseRefName,p.headRefName)),watches:(e.watches||[]).filter(p=>!String(p.key).startsWith("pr:"))},reports:{view:n.view,list:(e.reports||[]).filter(p=>(!n.repo||p.repo===n.repo)&&i(p.title,p.author,p.dispatch,p.repo)).sort(es)},notices:{list:(e.notices||[]).filter(p=>(!n.repo||!p.repo||p.repo===n.repo)&&(!n.noticeKind||p.kind===n.noticeKind)&&i(p.kind,p.text,p.repo))},foot:{version:e.version,repoUrl:e.repoUrl},modal:{modal:t.modal,item:c&&o(c),prefs:t.modal&&t.modal.type==="settings"?{view:n.view,lobs:n.lobs}:void 0}}}function us(e,t){let s=(e.prs||[]).find(c=>c.key===t);if(!s)return null;let n=(e.stacks||[]).find(c=>c.id===s.stackId),r=new Map((e.dispatches||[]).map(c=>[c.id,c])),i=(s.dispatchIds||[]).map(c=>{let u=r.get(c);return u?{id:c,verb:u.verb,modalKey:u.lane+":"+u.id}:{id:c,culled:!0}}),o=s.watch;return{pr:s,stack:n?{numbers:n.numbers,titles:n.numbers.map(c=>(e.prs||[]).find(u=>u.stackId===n.id&&u.number===c)?.title||""),position:s.position+1,size:n.numbers.length,floor:n.floor,nextNumber:n.nextNumber,nextMergeable:!!s.nextMergeable,blockedBy:s.blockedBy}:null,chain:i,watch:o?{key:o.key,owner:o.owner||"",lastCheckedAt:o.lastCheckedAt||null,lastError:o.lastError||null,cursor:o.cursor}:null}}function fs(e){return e?{text:e.lastError?"failing":"watching",at:e.lastCheckedAt||null}:{text:"no watch",at:null}}function ms(){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 hs(e){try{localStorage.setItem("spyglass",JSON.stringify(e))}catch{}}function gs(){try{return JSON.parse(localStorage.getItem("spyglass-lob-hidden")||"{}")||{}}catch{return{}}}function vs(e){try{localStorage.setItem("spyglass-lob-hidden",JSON.stringify(e))}catch{}}var pe,_s=new Set,_=()=>pe;function $s(e){pe=e}function G(e){pe={...pe,...e};for(let t of _s)t(pe)}var bs=e=>{_s.add(e)};function lt(e){let{modal:t,drafts:s}=_(),n=new Set(ot(e.attention||[],e.decisions||[]).map(i=>i.key)),r=Object.fromEntries(Object.entries(s).filter(([i])=>n.has(i)));G({snapshot:e,stale:!1,modal:t&&Q(e,t)?t:null,...Object.keys(r).length!==Object.keys(s).length?{drafts:r}:{}}),Ie()}var ks=()=>({text:"",files:[]});function A(e,t){let s=_().drafts;G({drafts:{...s,[e]:{...s[e]??ks(),...t}}})}function ys(e,t){let s=_().drafts[e]?.option;A(e,{option:s===t?void 0:t,error:void 0})}var Xn=e=>new Promise((t,s)=>{let n=new FileReader;n.onload=()=>t(String(n.result).replace(/^data:[^,]*,/,"")),n.onerror=()=>s(n.error),n.readAsDataURL(e)});async function ct(e,t){let s=_().snapshot?.answerLimits,n=[...t??[]],r=_().drafts[e]?.files??[],i=[],o=[];for(let c of n){let u=(/\\.[^.]+$/.exec(c.name)?.[0]??"").toLowerCase();if(s&&!s.extensions.includes(u))i.push(`${c.name}: type not accepted`);else if(s&&c.size>s.maxBytes)i.push(`${c.name}: larger than ${s.maxBytes} bytes`);else if(s&&r.length+o.length>=s.maxFiles)i.push(`${c.name}: at most ${s.maxFiles} files`);else try{o.push({name:c.name,bytes:c.size,data:await Xn(c)})}catch{i.push(`${c.name}: could not be read`)}}A(e,{files:[..._().drafts[e]?.files??[],...o],error:i.length?i.join("; "):void 0})}var Jn={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};async function ws(e,t){let s=[...t.clipboardData?.items??[]],n=new Date().toISOString().replace(/[:.]/g,"-").replace(/-\\d{3}Z$/,"Z"),r=s.filter(i=>i.kind==="file"&&i.type.startsWith("image/")).map(i=>i.getAsFile()).filter(i=>i!==null).map((i,o,c)=>{let u=`pasted-${n}${c.length>1?`-${o+1}`:""}${Jn[i.type]??".png"}`;return new File([i],u,{type:i.type})});r.length&&await ct(e,r)}function Ts(e,t){let s=(_().drafts[e]?.files??[]).filter((n,r)=>r!==t);A(e,{files:s})}async function xs(e){let t=_().snapshot?.focusToken,s=_().drafts[e]??ks();if(!(s.sending||s.sent)){if(!s.option&&!s.text.trim()&&s.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 n=await fetch("/requests",{method:"POST",headers:{"content-type":"application/json","x-lobstah-token":t},body:JSON.stringify({kind:"decision-answer",payload:{key:e,...s.option?{option:s.option}:{},...s.text.trim()?{text:s.text}:{},files:s.files.map(i=>({name:i.name,data:i.data}))}})}),r=await n.json();if(!n.ok||!r.ok){A(e,{sending:!1,error:r.reason??`The answer was refused (${n.status}).`});return}A(e,{sending:!1,sent:ls({option:s.option,text:s.text,files:s.files.length})})}catch{A(e,{sending:!1,error:"The answer could not be sent."})}}}function Ie(){let{snapshot:e,modal:t,reportText:s}=_();if(!e||!t)return;let n=t.type==="report"?(e.reports||[]).find(c=>c.key===t.key):t.type==="dispatch"?(e.reports||[]).find(c=>"report:"+t.key===c.key):void 0;if(!n||s[n.key]?.hash===n.stateHash)return;let r=n.key,i=n.stateHash,o=c=>G({reportText:{..._().reportText,[r]:{hash:i,...c}}});o({}),fetch(ds(r)).then(async c=>c.ok===!1?o({error:`report not found (${c.status})`}):o({text:await c.text()})).catch(()=>o({error:"report could not be read"}))}var Gs=()=>G({stale:!0}),Ss=(e,t)=>G({lightbox:{src:e,name:t}}),ue=()=>G({lightbox:null});function C(e,t){let{snapshot:s}=_(),n={type:e,key:t};G({modal:!s||Q(s,n)?n:null}),Ie()}function Z(){/^#report\\//.test(location.hash)&&history.replaceState(null,"","#deck"),G({modal:null})}async function Cs(e){let t=_().snapshot?.focusToken;if(t)try{let n=await(await fetch(`/api/focus/${encodeURIComponent(e)}`,{method:"POST",headers:{"x-lobstah-focus-token":t}})).json();G({focusResults:{..._().focusResults,[e]:n.message??n.reason??"Window focus failed."}})}catch{G({focusResults:{..._().focusResults,[e]:"Window focus failed."}})}}async function Ds(e,t){let s=_().snapshot?.focusToken;if(!s)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":s},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{lt(await(await fetch("/data")).json())}catch{}}function L(e){let t={..._().prefs,...e};hs(t),G({prefs:t})}function As(e){e!=="table"&&e!=="cards"||L({view:e})}var Rs=e=>L({lobs:e==="on"});function Is(e,t){let s={..._().lobHidden,[e]:t};vs(s),setTimeout(()=>G({lobHidden:s}),0)}async function Ms(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}var Es=function(e,t,s,n){var r;t[0]=0;for(var i=1;i<t.length;i++){var o=t[i++],c=t[i]?(t[0]|=o?1:2,s[t[i++]]):t[++i];o===3?n[0]=c:o===4?n[1]=Object.assign(n[1]||{},c):o===5?(n[1]=n[1]||{})[t[++i]]=c:o===6?n[1][t[++i]]+=c+"":o?(r=e.apply(c,Es(e,c,s,["",null])),n.push(r),c[0]?t[0]|=2:(t[i-2]=0,t[i]=r)):n.push(c)}return n},Ps=new Map;function Ls(e){var t=Ps.get(this);return t||(t=new Map,Ps.set(this,t)),(t=Es(this,t.get(e)||(t.set(e,t=(function(s){for(var n,r,i=1,o="",c="",u=[0],l=function(d){i===1&&(d||(o=o.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,"")))?u.push(0,d,o):i===3&&(d||o)?(u.push(3,d,o),i=2):i===2&&o==="..."&&d?u.push(4,d,0):i===2&&o&&!d?u.push(5,0,!0,o):i>=5&&((o||!d&&i===5)&&(u.push(i,0,o,r),i=6),d&&(u.push(i,d,0,r),i=6)),o=""},f=0;f<s.length;f++){f&&(i===1&&l(),l(f));for(var h=0;h<s[f].length;h++)n=s[f][h],i===1?n==="<"?(l(),u=[u],i=3):o+=n:i===4?o==="--"&&n===">"?(i=1,o=""):o=n+o[0]:c?n===c?c="":o+=n:n===\'"\'||n==="\'"?c=n:n===">"?(l(),i=1):i&&(n==="="?(i=5,r=o,o=""):n==="/"&&(i<5||s[f][h+1]===">")?(l(),i===3&&(u=u[0]),i=u,(u=u[0]).push(2,0,i),i=0):n===" "||n===" "||n===`\n`||n==="\\r"?(l(),i=2):o+=n),i===3&&o==="!--"&&(i=4,u=u[0])}return l(),u})(e)),t),arguments,[])).length>1?t:t[0]}var Ns=e=>Array.isArray(e)?e.map(Ns):e===""?null:e,Qn=(e,t,...s)=>ae(e,t,...s.map(Ns)),a=Ls.bind(Qn);var Pe,k,dt,Hs,pt=0,Vs=[],y=b,Os=y.__b,js=y.__r,Bs=y.diffed,Us=y.__c,Fs=y.unmount,qs=y.__;function Ks(e,t){y.__h&&y.__h(k,e,pt||t),pt=0;var s=k.__H||(k.__H={__:[],__h:[]});return e>=s.__.length&&s.__.push({}),s.__[e]}function Y(e){return pt=1,Zn(Xs,e)}function Zn(e,t,s){var n=Ks(Pe++,2);if(n.t=e,!n.__c&&(n.__=[s?s(t):Xs(void 0,t),function(c){var u=n.__N?n.__N[0]:n.__[0],l=n.t(u,c);u!==l&&(n.__N=[l,n.__[1]],n.__c.setState({}))}],n.__c=k,!k.__f)){var r=function(c,u,l){if(!n.__c.__H)return!0;var f=!1,h=n.__c.props!==c;if(n.__c.__H.__.some(function(m){if(m.__N){f=!0;var p=m.__[0];m.__=m.__N,m.__N=void 0,p!==m.__[0]&&(h=!0)}}),i){var d=i.call(this,c,u,l);return f?d||h:d}return!f||h};k.__f=!0;var i=k.shouldComponentUpdate,o=k.componentWillUpdate;k.componentWillUpdate=function(c,u,l){if(this.__e){var f=i;i=void 0,r(c,u,l),i=f}o&&o.call(this,c,u,l)},k.shouldComponentUpdate=r}return n.__N||n.__}function zs(e,t){var s=Ks(Pe++,7);return tr(s.__H,t)&&(s.__=e(),s.__H=t,s.__h=e),s.__}function Yn(){for(var e;e=Vs.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(Me),t.__h.some(ut),t.__h=[]}catch(s){t.__h=[],y.__e(s,e.__v)}}}y.__b=function(e){k=null,Os&&Os(e)},y.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),qs&&qs(e,t)},y.__r=function(e){js&&js(e),Pe=0;var t=(k=e.__c).__H;t&&(dt===k?(t.__h=[],k.__h=[],t.__.some(function(s){s.__N&&(s.__=s.__N),s.u=s.__N=void 0})):(t.__h.some(Me),t.__h.some(ut),t.__h=[],Pe=0)),dt=k},y.diffed=function(e){Bs&&Bs(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Vs.push(t)!==1&&Hs===y.requestAnimationFrame||((Hs=y.requestAnimationFrame)||er)(Yn)),t.__H.__.some(function(s){s.u&&(s.__H=s.u,s.u=void 0)})),dt=k=null},y.__c=function(e,t){t.some(function(s){try{s.__h.some(Me),s.__h=s.__h.filter(function(n){return!n.__||ut(n)})}catch(n){t.some(function(r){r.__h&&(r.__h=[])}),t=[],y.__e(n,s.__v)}}),Us&&Us(e,t)},y.unmount=function(e){Fs&&Fs(e);var t,s=e.__c;s&&s.__H&&(s.__H.__.some(function(n){try{Me(n)}catch(r){t=r}}),s.__H=void 0,t&&y.__e(t,s.__v))};var Ws=typeof requestAnimationFrame=="function";function er(e){var t,s=function(){clearTimeout(n),Ws&&cancelAnimationFrame(t),setTimeout(e)},n=setTimeout(s,35);Ws&&(t=requestAnimationFrame(s))}function Me(e){var t=k,s=e.__c;typeof s=="function"&&(e.__c=void 0,s()),k=t}function ut(e){var t=k;e.__c=e.__(),k=t}function tr(e,t){return!e||e.length!==t.length||t.some(function(s,n){return s!==e[n]})}function Xs(e,t){return typeof t=="function"?t(e):t}var V=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=>a`<span data-age=${e??""}>${V(e)}</span>`,Le=e=>e.activity&&a`<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>`,sr=e=>e&&/^https?:\\/\\//i.test(e)?e:void 0,Ne=e=>{let t=e.waiting;if(!t)return;let s=sr(t.link),n=s;try{s&&(n=new URL(s).host+new URL(s).pathname.replace(/\\/$/,""))}catch{n=s}return a`<div class="waiting">${e.verb}: waiting on ${t.on} \xB7 ${v(t.since)}${s&&[" \\xB7 ",a`<a href=${s} target="_blank" rel="noopener noreferrer" onClick=${D}>${n}</a>`]}</div>`},nr=12,Js=e=>e!==void 0&&e.length>nr,N=e=>Js(e)?e:void 0,H=e=>Js(e)?" long":"",w=(e,t)=>()=>C(e,t),D=e=>e.stopPropagation(),rr=e=>e.sessionId?(e.harness==="codex"?"codex resume ":"claude --resume ")+e.sessionId:void 0;function K(e){if(e.requested)return a`<span class="dim">Requested \u2014 no window yet</span>`;if(e.starting)return a`<span class="dim">${e.starting.failedAt?"Did not start":"Starting \\u2014 no window yet"}</span>`;if(!e.live){let n=rr(e);return n?a`<span class="dim">Resume: <code onClick=${D}>${n}</code></span>`:a`<span class="dim">Resume command unavailable</span>`}let t=_();return!t.snapshot?.focusSupported&&!e.link?a`<span class="dim">Window focus is not supported here</span>`:a`<span class="winaction"><button class="btn open" title="open this trap\'s window" onClick=${n=>{D(n),Cs(e.trapId)}}>\u2197 open</button>${e.link&&[" ",a`<a href=${e.link} onClick=${D}>Session link</a>`]}${t.focusResults[e.trapId]&&[" ",a`<span class="dim">${t.focusResults[e.trapId]}</span>`]}</span>`}function R(e,t,s){return t.length?a`<div class="wrap"><table><tbody><tr>${e.map(n=>a`<th>${n}</th>`)}</tr>${t}</tbody></table></div>`:a`<div class="empty">${s}</div>`}function ir({text:e}){let[t,s]=Y(null),n=r=>async()=>{await Ms(e)&&(s(r),setTimeout(()=>s(null),1e3))};return a`<div class="cmd"><code class=${t==="code"?"copied":void 0} title="click to copy" onClick=${n("code")}>${e}</code><button title="copy" onClick=${n("button")}>${t==="button"?"\\u2713":"\\u29C9"}</button></div>`}var S=(e,t)=>a`<${ir} key=${t} text=${e} />`,fe=(e,t,s="thumb")=>a`<button\n type="button"\n class=${s}\n title=${"view "+t}\n onClick=${n=>{D(n),Ss(e,t)}}\n >\n <img src=${e} alt=${t} loading="lazy" />\n </button>`,ee=(e,t)=>e.map(s=>[a`<div class="sub">${s.name} \xB7 ${s.type} \xB7 ${s.bytes} bytes</div>`,t&&as(s.name)&&fe(t(s.name),s.name),S(s.path)]),Qs=/\\bwt:([a-z0-9][a-z0-9-]*)/g,ft=e=>_().snapshot?.trapNames?.[e],O=e=>e.replace(Qs,(t,s,n)=>{let r=ft(s);return r&&!Zs(e,n,t.length,r)?r:t}),Zs=(e,t,s,n)=>e.slice(Math.max(0,t-n.length-2),t)===`${n} (`&&e[t+s]===")";function He(e){let t="wt:"+e,s=ft(e)??t;return _().snapshot?.traps.some(r=>r.trapId===e)?a`<a class="trapname" href="#traps" title=${t} onClick=${r=>{r.preventDefault(),D(r),C("trap",e)}}>${s}</a>`:a`<span class="trapname" title=${t}>${s}</span>`}var Ee=e=>{let t=/^wt:([a-z0-9][a-z0-9-]*)$/.exec(e);return t?He(t[1]):e};function j(e,t=1/0){let s=[],n=0;for(let c of e.matchAll(Qs)){c.index>n&&s.push({text:e.slice(n,c.index)});let u=ft(c[1]);s.push(u&&Zs(e,c.index,c[0].length,u)?{text:c[0]}:{text:u??c[0],trapId:c[1]}),n=c.index+c[0].length}n<e.length&&s.push({text:e.slice(n)});let r=s.reduce((c,u)=>c+u.text.length,0),i=r>t?t-1:1/0,o=[];for(let c of s){if(i<=0)break;c.text.length<=i?o.push(c.trapId?He(c.trapId):c.text):o.push(c.text.slice(0,i)),i-=c.text.length}return r>t&&o.push("\\u2026"),o}var mt=e=>e.log.flatMap((t,s)=>[s?`\n`:"",t.at+" "+t.verb,...t.note?[" ",...j(t.note)]:[]]);function Ys(e){let t=[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`);return a`${e.waiting&&[a`<div class="sec">waiting</div>`,Ne(e)]}${e.activity&&[a`<div class="sec">activity</div>`,Le(e)]}${t&&[a`<div class="sec">progress</div>`,a`<pre>${t}</pre>`]}<div class="sec">brief</div><pre>${e.brief}</pre>${e.attachments.length>0&&[a`<div class="sec">attachments (${e.attachments.length})</div>`,ee(e.attachments,s=>rt(e.lane,e.id,s))]}${e.messageAttachments.length>0&&[a`<div class="sec">message attachments (${e.messageAttachments.length})</div>`,ee(e.messageAttachments,s=>rt(e.lane,e.id,s))]}${e.followUp&&[a`<div class="sec">forks</div>`,a`<pre>${e.followUp}</pre>`]}<div class="sec">log</div><div class="loglines">${e.log.length?mt(e):"no entries yet"}</div>${e.inbox.length>0&&[a`<div class="sec">inbox</div>`,a`<div class="loglines">${e.inbox.join(`\n---\n`)}</div>`]}${e.awaitingReply&&[a`<div class="sec">awaiting reply</div>`,a`<div>${e.awaitingReply.line} \xB7 from ${e.awaitingReply.from} \xB7 ${v(e.awaitingReply.sentAt)} ago</div>`]}${e.evidence&&[a`<div class="sec">evidence</div>`,a`<div class="loglines">${JSON.stringify(e.evidence)}</div>`]}`}function me(e){return e.for?[Ee(e.for),e.evidence&&e.evidence.deliveredTo?[" ",a`<span class="ok">\u2713delivered</span>`]:[" ",a`<span class="warn">waiting</span>`]]:e.claimedBy?Ee(e.claimedBy):""}function te(e){let t=e.evidence&&(e.evidence.prUrl||e.evidence.pr&&e.evidence.pr.url);if(!t)return"";let s=e.prBadge;return[a`<a href=${t} target="_blank" rel="noopener" onClick=${D}>PR</a>`,s&&[" ",a`<span class=${"badge "+E(s)} title=${"observed "+s.observedAt}>${s.text}</span>`],e.prGate&&[" ",a`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]]}var or={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready",landed:"landed",watch:"watch"},ht={"pr:review":"bad","pr:checks":"bad","pr:conflict":"pr-conflicts","pr:ready":"ok","pr:draft":"dim",watch:"warn"},en=e=>or[e]||"";var Oe=e=>a`<a href=${e.url} target="_blank" rel="noopener" onClick=${D}>#${e.number}</a>`,je=e=>a`<span class="prname" title=${e.title||void 0}><b>#${e.number}</b>${e.title&&[" ",e.title]}</span>`;function se(e,t,s){return e.flatMap((n,r)=>{let i=t.get(n)||void 0,o=n===s?a`<b title=${i}>#${n}</b>`:a`<span title=${i}>#${n}</span>`;return r?[" \\u2192 ",o]:[o]})}function he(e){let t=e.checks;return t.passed+"/"+t.total+" passed"+(t.failed?" \\xB7 "+t.failed+" failed":"")+(t.pending?" \\xB7 "+t.pending+" pending":"")}function Be(e){let t=e.review||{};return(e.reviewDecision||"")+(t.unresolvedThreads?" \\xB7 "+t.unresolvedThreads+" unresolved":"")+(t.changesRequested?" \\xB7 changes requested":"")}function ge(e){return[e.mergeStateStatus,e.nextMergeable?[" \\xB7 ",a`<span class="ok">next mergeable</span>`]:e.blockedBy?" \\xB7 blocked by #"+e.blockedBy:""]}function gt(e){let t=fs(e);return e?[t.text," \\xB7 ",t.at?[v(t.at)," ago"]:"never checked"]:a`<span class="dim">${t.text}</span>`}function ve(e){if(e.requested)return{stale:!1,listen:[a`<span class="dot"></span>`,a`<span class="dim">requested</span>`],hb:a`<span class="dim">\u2014</span>`};if(e.starting)return{stale:!1,listen:e.starting.failedAt?[a`<span class="dot bad"></span>`,a`<span class="bad">start failed</span>`]:[a`<span class="dot warn"></span>`,"starting"],hb:a`<span class="dim">\u2014</span>`};if(!e.live)return{stale:!1,listen:[a`<span class="dot"></span>`,a`<span class="dim">signed off</span>`],hb:a`<span class="dim">\u2014</span>`};let t=Date.now()-Date.parse(e.heartbeatAt)>18e5,s=e.listening??(!!e.firstParkedAt&&!t);return{stale:t,listen:s?[a`<span class="dot ok"></span>`,"listening"]:[a`<span class="dot warn"></span>`,"not listening"],hb:a`<span class=${t?"bad":"ok"}>${t&&"stale "}${v(e.heartbeatAt)} ago</span>`}}function vt(e){if(e.requested)return{kind:"requested",helmOn:!!_().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(s=>s.id===e.claimed&&s.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 ar(e){let t=vt(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 tn=e=>e.waiting?`waiting on ${e.waiting.on}`:e.note||"waiting",sn=e=>e.brief.split(/\\r?\\n/,1)[0]?.trim().slice(0,40)||"(no title)";function _e(e){let t=vt(e),s=a`<span class=${"dot trapdot "+ar(e)}></span>`;if(t.kind==="requested")return[s,a`<span class="dim">${nn(e,t.helmOn)}</span>`];if(t.kind==="starting")return[s,"starting \\xB7 waiting for its session to sign on"];if(t.kind==="start failed")return[s,a`<span class="bad">start failed</span>`," \\xB7 ",t.reason];if(t.kind==="signed off")return[s,a`<span class="dim">signed off</span>`];if(t.kind==="idle")return[s,"idle \\xB7 ",t.listening?"listening":"not listening"];let n=t.current;return t.kind==="parked"?[s,"parked \\xB7 ",tn(n)]:[s,"working \\xB7 ",a`<a href="#dispatches" onClick=${i=>{i.preventDefault(),D(i),C("dispatch",`${n.lane}:${n.id}`)}}>${n.id.slice(0,8)}</a>`," \\xB7 ",sn(n),n.activity&&[" \\xB7 ",n.activity.summary," ",v(n.activity.at)," ago"]]}var nn=(e,t)=>`requested \\xB7 ${e.repo??""} \\xB7 ${e.harness??""} \\xB7 ${t?"waiting for the helm":"waiting for a helm"}`;function z(e){let t=e.starting?.commands;return t?.length?a`<div class="startcmds" onClick=${D}><div class="dim">start it: run one in a terminal</div>${t.map(s=>S(s.command,s.harness))}</div>`:null}function Ue(){let t=_().snapshot?.repoKeys??[],[s,n]=Y(!1),[r,i]=Y(""),[o,c]=Y("claude"),[u,l]=Y(null),f=r||t[0]||"",h=async d=>{d.preventDefault();let m=await Ds(f,o);l(m??null),m||n(!1)};return s?a`<form class="newtrap" onClick=${D} onSubmit=${h}>\n <label>repo <select name="repo" value=${f} onChange=${d=>i(d.target.value)}>${t.map(d=>a`<option value=${d}>${d}</option>`)}</select></label>\n <label>harness <select name="harness" value=${o} onChange=${d=>c(d.target.value)}><option value="claude">claude</option><option value="codex">codex</option></select></label>\n <button class="btn" type="submit" disabled=${!f}>Request</button>\n <button class="btn" type="button" onClick=${()=>n(!1)}>Cancel</button>\n ${u&&a`<span class="bad">${u}</span>`}\n </form>`:a`<span class="newtrap"><button class="btn" onClick=${d=>(D(d),n(!0),l(null))}>+ New trap</button></span>`}function Fe(e){let t=vt(e);if(t.kind==="requested")return nn(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 ${tn(t.current)}`;let s=t.current;return[`working \\xB7 ${s.id.slice(0,8)} \\xB7 ${sn(s)}`,s.activity&&`${s.activity.summary} ${V(s.activity.at)} ago`].filter(Boolean).join(" \\xB7 ")}function _t(e){let t=e.messages.filter(s=>s.state==="pending").length;return e.messages.length?["\\u2709 "+e.messages.length,t>0&&[" ",a`<span class="warn">(${t} pending)</span>`]]:null}var qe=e=>()=>{let t=ce(e.key);C(t.type,t.key)};function $t(e){let t=de(e);return{nodes:[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked?" \\xB7 acked":""],text:[t,`${V(e.filedAt)} ago`,e.acked?"acked":""].filter(Boolean).join(" \\xB7 ")}}function lr(e){let t=$t(e);return a`<div key=${e.key} class=${"card"+(e.acked?" acked":"")} onClick=${qe(e)}><div class="top"><b title=${e.title}>${e.title}</b></div><div class="meta" title=${t.text}>${t.nodes}</div></div>`}function cr(e){return a`<tr key=${e.key} class=${"rowhead"+(e.acked?" acked":"")} onClick=${qe(e)}><td class="grow">${e.title}</td><td>${de(e)}</td><td>${v(e.filedAt)}</td><td>${e.acked?"acked":""}</td></tr>`}function rn({inp:e}){return e.view==="cards"?e.list.length?a`<div class="cards">${e.list.map(lr)}</div>`:a`<div class="empty">no reports match</div>`:R(["title","from","filed","acked"],e.list.map(cr),"no reports match")}function ln(e){let t=e.trim();return/^(https?:\\/\\/|mailto:|#)/i.test(t)?t:void 0}function cn(e){let t=e.trim();return/^[^/\\\\:?#]+$/.test(t)&&t!=="."&&t!==".."?t:void 0}function on(e,t,s,n){let r=0;for(let i=t;i<e.length;i++){if(e[i]==="\\\\"){i++;continue}if(e[i]===s)r++;else if(e[i]===n){if(r===0)return i;r--}}return-1}function an(e,t){let s=on(e,t+1,"[","]");if(s<0||e[s+1]!=="(")return;let n=on(e,s+2,"(",")");if(n<0)return;let r=e.slice(s+2,n).trim().replace(/\\s+"[^"]*"$/,"").replace(/^<(.*)>$/,"$1");return{text:e.slice(t+1,s),target:r,end:n+1}}function U(e){let t=[],s="",n=()=>{s&&t.push({t:"text",v:s}),s=""};for(let r=0;r<e.length;){let i=e[r];if(i==="\\\\"&&r+1<e.length&&/[\\\\`*_{}[\\]()#+\\-.!|<>~]/.test(e[r+1])){s+=e[r+1],r+=2;continue}if(i==="`"){let o=/^`+/.exec(e.slice(r))[0],c=e.indexOf(o,r+o.length);if(c>0){n(),t.push({t:"code",v:e.slice(r+o.length,c).replace(/^ (.*) $/,"$1")}),r=c+o.length;continue}}if(i==="!"&&e[r+1]==="["){let o=an(e,r+1);if(o){n(),t.push({t:"img",alt:o.text,src:o.target}),r=o.end;continue}}if(i==="["){let o=an(e,r);if(o){n(),t.push({t:"a",href:o.target,c:U(o.text)}),r=o.end;continue}}if((i==="*"||i==="_")&&e[r+1]===i){let o=e.indexOf(i+i,r+2);if(o>r+2){n(),t.push({t:"b",c:U(e.slice(r+2,o))}),r=o+2;continue}}if(i==="*"||i==="_"&&(r===0||!/\\w/.test(e[r-1]))){let o=r+1;for(;(o=e.indexOf(i,o))>0&&(e[o+1]===i||i==="_"&&/\\w/.test(e[o+1]??""));)o+=2;if(o>r+1&&e[r+1]!==" "){n(),t.push({t:"i",c:U(e.slice(r+1,o))}),r=o+1;continue}}if(i===`\n`){/ {2,}$/.test(s)||s.endsWith("\\\\")?(s=s.replace(/( {2,}|\\\\)$/,""),n(),t.push({t:"br"})):s+=" ",r++;continue}s+=i,r++}return n(),t}var dn=/^ {0,3}(`{3,}|~{3,})\\s*([^`\\s]*)/,pn=/^ {0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/,un=/^ {0,3}([-*_])(\\s*\\1){2,}\\s*$/,yt=/^( {0,3})([-*+])\\s+(.*)$/,wt=/^( {0,3})(\\d{1,9})[.)]\\s+(.*)$/,We=/^ {0,3}>\\s?(.*)$/,dr=/^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;function bt(e){let t=e.trim();t.startsWith("|")&&(t=t.slice(1)),t.endsWith("|")&&!t.endsWith("\\\\|")&&(t=t.slice(0,-1));let s=[],n="";for(let r=0;r<t.length;r++)t[r]==="\\\\"&&t[r+1]==="|"?(n+="|",r++):t[r]==="|"?(s.push(n.trim()),n=""):n+=t[r];return s.push(n.trim()),s}var kt=e=>dn.test(e)||pn.test(e)||un.test(e)||yt.test(e)||wt.test(e)||We.test(e);function $e(e){let t=e.replace(/\\r\\n?/g,`\n`).replace(/\\t/g," ").split(`\n`),s=[],n=0;for(;n<t.length;){let r=t[n];if(!r.trim()){n++;continue}let i=dn.exec(r);if(i){let f=i[1],h=[];for(n++;n<t.length&&!new RegExp(`^ {0,3}${f[0]}{${f.length},}\\\\s*$`).test(t[n]);)h.push(t[n++]);n++,s.push({t:"code",lang:i[2]??"",v:h.join(`\n`)});continue}let o=pn.exec(r);if(o){s.push({t:"h",level:o[1].length,c:U(o[2])}),n++;continue}if(un.test(r)){s.push({t:"hr"}),n++;continue}if(We.test(r)){let f=[];for(;n<t.length&&t[n].trim()&&(We.test(t[n])||!kt(t[n]));)f.push(We.exec(t[n])?.[1]??t[n]);s.push({t:"quote",c:$e(f.join(`\n`))}),n+=f.length;continue}let c=yt.exec(r),u=wt.exec(r);if(c||u){let f=!c,h=f?wt:yt,d=[];for(;n<t.length;){let m=t[n],p=h.exec(m);if(p&&p[1].length<=3){d.push([p[3]]),n++;continue}if(!m.trim()){if(n+1<t.length&&/^ {2,}\\S/.test(t[n+1])){d.at(-1).push(""),n++;continue}break}if(/^ {2,}\\S/.test(m)){d.at(-1).push(m.replace(/^ {2,4}/,"")),n++;continue}if(kt(m))break;d.at(-1).push(m.trim()),n++}s.push({t:"list",ordered:f,start:f?Number(u[2]):1,items:d.map(m=>$e(m.join(`\n`)))});continue}if(r.includes("|")&&n+1<t.length&&dr.test(t[n+1])&&t[n+1].includes("-")){let f=bt(r),h=bt(t[n+1]).map(m=>m.startsWith(":")&&m.endsWith(":")?"center":m.endsWith(":")?"right":m.startsWith(":")?"left":"");n+=2;let d=[];for(;n<t.length&&t[n].trim()&&t[n].includes("|");){let m=bt(t[n++]);d.push(f.map((p,g)=>U(m[g]??"")))}s.push({t:"table",align:f.map((m,p)=>h[p]??""),head:f.map(U),rows:d});continue}let l=[];for(;n<t.length&&t[n].trim()&&!kt(t[n])&&!(l.length&&/^ {0,3}(=+|-+)\\s*$/.test(t[n]));)l.push(t[n++].replace(/^ +/,""));if(l.length===0){s.push({t:"p",c:U(r.trim())}),n++;continue}s.push({t:"p",c:U(l.join(`\n`))})}return s}function F(e,t){return t.map(s=>{switch(s.t){case"text":return s.v;case"code":return a`<code>${s.v}</code>`;case"b":return a`<strong>${F(e,s.c)}</strong>`;case"i":return a`<em>${F(e,s.c)}</em>`;case"br":return a`<br />`;case"a":{let n=ln(s.href);return n?a`<a href=${n} target="_blank" rel="noopener noreferrer">${F(e,s.c)}</a>`:F(e,s.c)}case"img":{let n=cn(s.src);return n?fe(e(n),s.alt||n,"mdimg"):a`<span class="dim">[image not shown: ${s.alt||s.src}]</span>`}}})}function Ve(e,t){return t.map(s=>{switch(s.t){case"h":{let n=F(e,s.c);return s.level===1?a`<h1>${n}</h1>`:s.level===2?a`<h2>${n}</h2>`:s.level===3?a`<h3>${n}</h3>`:a`<h4>${n}</h4>`}case"p":return a`<p>${F(e,s.c)}</p>`;case"code":return a`<pre class="mdcode"><code>${s.v}</code></pre>`;case"hr":return a`<hr />`;case"quote":return a`<blockquote>${Ve(e,s.c)}</blockquote>`;case"list":{let n=s.items.map(r=>a`<li>${Ve(e,r)}</li>`);return s.ordered?a`<ol start=${s.start}>${n}</ol>`:a`<ul>${n}</ul>`}case"table":return a`<div class="mdtable"><table><thead><tr>${s.head.map((n,r)=>a`<th style=${s.align[r]?"text-align:"+s.align[r]:void 0}>${F(e,n)}</th>`)}</tr></thead><tbody>${s.rows.map(n=>a`<tr>${n.map((r,i)=>a`<td style=${s.align[i]?"text-align:"+s.align[i]:void 0}>${F(e,r)}</td>`)}</tr>`)}</tbody></table></div>`}})}function pr({r:e,text:t}){let s=t?.text!==void 0?Ve(n=>at(e.key,n),$e(t.text)):t?.error?a`<div class="bad">${t.error}</div>`:a`<div class="dim">loading\u2026</div>`;return a`<div class="mdpage" data-report=${e.key}>${s}</div>`}function fn({text:e,fileUrl:t}){return a`<div class="mdpage">${Ve(t,$e(e))}</div>`}function ur(e){let t=de(e);return[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked&&[" \\xB7 ",a`<span class="ok">acked</span>`]]}function Tt({r:e,text:t,heading:s}){return[s&&a`<div class="sec">report \xB7 ${e.title}</div>`,a`<div class="sub">${ur(e)}</div>`,a`<${pr} r=${e} text=${t} />`,e.attachments.length>0&&[a`<div class="sec">report attachments (${e.attachments.length})</div>`,ee(e.attachments,n=>at(e.key,n))],!e.acked&&[a`<div class="sec">ack</div>`,S("lobstah attention ack "+e.key)]]}var fr=/\\.(png|jpe?g|gif|webp)$/i,mr=e=>{e.style.height="auto",e.style.height=e.scrollHeight+"px"};function hr(e,t){return t.length?a`<div class="dfiles">${t.map(s=>fr.test(s.name)?a`<span key=${s.name}>${fe(it(e,s.name),s.name,"dimg")}</span>`:a`<div key=${s.name} class="dfile"><span>${s.name}</span> <span class="dim">\xB7 ${s.type} \xB7 ${s.bytes} bytes \xB7 </span><code>${s.path}</code></div>`)}</div>`:null}function gr(e,t,s){let n=e.key,r=e.kind==="decision"?e.options:[],i=t?.text??"",o=t?.files??[],c=!!t?.sending;return[r.length>0&&a`<div class="doptions">${r.map(u=>a`<button key=${u} type="button" class=${"btn dopt"+(t?.option===u?" on":"")} aria-pressed=${t?.option===u?"true":"false"} disabled=${c} onClick=${()=>ys(n,u)}>${u}</button>`)}</div>`,a`<textarea\n class="danswer"\n rows="2"\n placeholder=${r.length?"Add to your answer, or answer in your own words":"Your answer"}\n value=${i}\n disabled=${c}\n onInput=${u=>{let l=u.currentTarget;mr(l),A(n,{text:l.value,error:void 0})}}\n onPaste=${u=>{ws(n,u)}}\n ></textarea>`,a`<div class="dfoot">\n <label class="btn dattach" title="attach images or files">attach<input type="file" multiple accept=${s} disabled=${c} onChange=${u=>{let l=u.currentTarget;ct(n,l.files).then(()=>{l.value=""})}} /></label>\n ${o.map((u,l)=>a`<span key=${u.name+l} class="dchip">${u.name}<button type="button" class="dx" title="remove" disabled=${c} onClick=${()=>Ts(n,l)}>\xD7</button></span>`)}\n ${t?.error&&a`<span class="bad derr">${t.error}</span>`}\n <button type="button" class="btn dsend" disabled=${c} onClick=${()=>{xs(n)}}>${c?"Sending\\u2026":"Send"}</button>\n </div>`]}function vr(e,t,s,n){let r=e.dispatch,i=e.lane??"work",c=[r&&a`<a class="dlink" href="#" onClick=${l=>{l.preventDefault(),w("dispatch",i+":"+r)()}}>${r.slice(0,8)}</a>`,e.repo,[v(e.at)," ago"]].filter(Boolean).flatMap((l,f)=>f?[" \\xB7 ",l]:[l]),u="dcard"+(e.kind==="question"?" plain":"")+(t?.sent?" answered":"")+(s?" focus":"");return a`<div key=${e.key} class=${u} data-decision=${e.key}>\n <div class="dtop">\n ${e.kind==="question"&&a`<span class=${"badge "+(e.verb==="blocked"?"bad":"warn")}>${e.verb}</span>`}\n <b class="dtitle">${e.kind==="decision"?e.title:j(e.note)}</b>\n <span class="dmeta dim">${c}</span>\n </div>\n ${e.kind==="decision"&&e.detail.trim()&&a`<${fn} text=${e.detail} fileUrl=${l=>it(e.key,l)} />`}\n ${e.kind==="decision"&&hr(e.key,e.attachments)}\n ${t?.sent?a`<div class="danswered ok">answered \xB7 ${t.sent}</div>`:gr(e,t,n)}\n </div>`}function mn({cards:e,drafts:t,focus:s,extensions:n}){let r=n.join(","),i=e.length?a`<div class="dcards">${e.map(o=>vr(o,t[o.key],o.key===s,r))}</div>`:a`<div class="empty">none</div>`;return a`<section class="decisions"><h2>decisions</h2>${i}</section>`}function kr(e,t){let s=e.badge&&a`<span class=${"badge "+(e.badge.tone||"dim")+H(e.badge.text)} title=${N(e.badge.text)}>${e.badge.text}</span>`;return t==="cards"?a`<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}</div>${e.meta&&a`<div class="meta" title=${e.metaText}>${e.meta}</div>`}${e.extra}${e.action&&a`<div class="foot"><span class="footact">${e.action}</span></div>`}</div>`:a`<div key=${e.key} class=${"deckline"+(e.open?" click":"")+(e.acked?" acked":"")} onClick=${e.open}>${s&&[s," "]}<b>${e.title}</b>${e.meta&&[" ",a`<span class="dim">\xB7 ${e.meta}</span>`]}${e.action&&[" ",a`<span class="dim">\xB7 </span>`,e.action]}${e.extra}</div>`}var hn=(e,t)=>e>0&&a`<a class="deckmore" href=${"#"+t}>+${e} more \u2192</a>`;function Ke(e,t,s,n,r,i){let o=t.slice(0,n),c=o.map(l=>kr(l,r)),u=o.length?r==="cards"?a`<div class="cards">${c}</div>`:c:a`<div class="empty">none</div>`;return a`<section><h2><a href=${"#"+s}>${e} \u2192</a></h2>${i&&a`<div class="tabhead">${i}</div>`}${u}${hn(t.length-o.length,s)}</section>`}function yr(e,t,s,n){let r=t.find(l=>l.number===e.nextNumber)||t[0],i=se(e.numbers,new Map(t.map(l=>[l.number,l.title]))),o=r?"next #"+r.number:"nothing mergeable";if(n==="cards"){let l=f=>{let h=s.get(f.key)||[],d=h.length>0&&h.every(g=>g.acked),m=h.length?h.map(g=>a`<span class=${"badge "+(ht[g.kind]||"dim")}>${en(g.kind)}</span>`):a`<span class=${"badge "+E(f.badge)+H(f.badge.text)} title=${N(f.badge.text)}>${f.badge.text}</span>`,p=`${f.repo} \\xB7 ${f.badge.text}${d?" \\xB7 acked":""}`;return a`<div key=${f.key} class=${"card"+(d?" acked":"")} onClick=${w("pr",f.key)}><div class="top">${je(f)}${m}</div><div class="meta" title=${p}>${p}</div></div>`};return a`<div key=${e.id} class="deckstack"><div class="dim">${i} \xB7 ${o}</div><div class="cards">${t.map(l)}</div></div>`}let c=t.flatMap(l=>(s.get(l.key)||[]).map(f=>a`<span class=${"badge "+(ht[f.kind]||E(l.badge))+(f.acked?" acked":"")}>#${l.number} ${l.badge.text}</span>`)),u=c.flatMap((l,f)=>f?[" ",l]:[l]);return a`<div key=${e.id} class=${"deckline"+(r?" click":"")} onClick=${r&&w("pr",r.key)}><b>${i}</b> <span class="dim">\xB7 ${o}</span>${c.length>0&&[" \\xB7 ",u]}</div>`}function wr(e,t){let s=e.stacks.slice(0,3),n=new Map;for(let i of e.prAttention){let o=n.get(i.key)||[];o.push(i),n.set(i.key,o)}let r=s.length?s.map(i=>yr(i,e.prs.filter(o=>o.stackId===i.id).sort((o,c)=>o.position-c.position),n,t)):a`<div class="empty">none</div>`;return a`<section><h2><a href="#prs">PRs \u2192</a></h2>${r}${hn(e.stacks.length-s.length,"prs")}</section>`}function gn({inp:e,drafts:t,focus:s,extensions:n}){let r=e.view,i=e.inflight.map(l=>({key:l.lane+":"+l.id,title:[l.id.slice(0,8)," ",l.repo||""],badge:{text:l.verb,tone:l.verb==="needs-decision"||l.verb==="blocked"?"bad":"dim"},meta:[j(l.note||"",90),l.verbAt&&[" \\xB7 ",v(l.verbAt)," ago"],(l.for||l.claimedBy)&&[" \\xB7 ",Ee(l.for||l.claimedBy)]],metaText:[O(l.note||""),l.verbAt&&`${V(l.verbAt)} ago`,O(l.for||l.claimedBy||"")].filter(Boolean).join(" \\xB7 "),open:w("dispatch",l.lane+":"+l.id)})),o=e.landed.map(l=>({key:l.key,title:[l.id.slice(0,8)," ",l.repo||"",l.unreported&&[" ",a`<span class="badge warn unreported">unreported</span>`]],badge:{text:l.verb,tone:l.verb==="failed"?"bad":"ok"},meta:[j(l.note||"",90)," \\xB7 ",v(l.at)," ago"],metaText:`${O(l.note||"")} \\xB7 ${V(l.at)} ago`,open:w("dispatch",l.lane+":"+l.id)})),c=e.reports.map(l=>{let f=$t(l);return{key:l.key,title:l.title,meta:f.nodes,metaText:f.text,open:qe(l),acked:!!l.acked}}),u=e.traps.map(({x:l})=>({key:l.trapId,title:"\\u{1FAA4} "+(l.label??`wt:${l.trapId}`),badge:l.requested?{text:"requested",tone:"dim"}:l.starting?{text:l.starting.failedAt?"start failed":"starting",tone:l.starting.failedAt?"bad":"warn"}:{text:l.live?l.harness||"live":"signed off",tone:l.live?"ok":"dim"},meta:[l.repo||""," \\xB7 ",_e(l)],metaText:`${l.repo||""} \\xB7 ${Fe(l)}`,action:K(l),extra:z(l),open:w("trap",l.trapId)}));return a`<div class="deckgrid"><${mn} cards=${e.decisions} drafts=${t} focus=${s} extensions=${n} />${Ke("in flight",i,"dispatches",4,r)}${Ke("Landed \\xB7 24h",o,"dispatches",8,r)}${Ke("reports",c,"reports",8,r)}${Ke("traps",u,"traps",8,r,a`<${Ue} />`)}${wr(e,r)}</div>`}function Tr(e,t){if(!t)return e;let s=new Map(e.map(i=>[i.id,i])),n=i=>{let o=i,c=new Set;for(;o.followUp&&s.has(o.followUp)&&!c.has(o.id);)c.add(o.id),o=s.get(o.followUp);return o.id},r=new Map;for(let i of e){let o=n(i),c=r.get(o)||[];c.push(i),r.set(o,c)}return[...r.values()].sort((i,o)=>o[0].sort-i[0].sort).flatMap(i=>i.sort((o,c)=>o.id===n(o)?-1:c.id===n(c)?1:o.sort-c.sort))}function xr(e,t){let s=e.lane+":"+e.id;return a`<tr key=${s} class="rowhead" onClick=${w("dispatch",s)}><td>${t&&e.followUp&&a`<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">${j(e.note??"",90)}${Ne(e)}${Le(e)}</td><td>${v(e.verbAt)}</td><td>${me(e)}</td><td>${te(e)}</td></tr>`}function Gr(e){let t=e.lane+":"+e.id;return a`<div key=${t} class="card" onClick=${w("dispatch",t)}><div class="top"><b>${e.id.slice(0,8)}</b><span class=${"badge v-"+e.verb+H(e.verb)} title=${N(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&&a`<div class="note" title=${O(e.note)}>${j(e.note)}</div>`}${Ne(e)}${Le(e)}<div class="foot">${me(e)} ${te(e)}</div></div>`}function vn({inp:e}){let t=e.list;return e.view==="cards"?t.length?a`<div class="cards">${t.map(Gr)}</div>`:a`<div class="empty">no dispatches match</div>`:R(["id","lane / bucket","repo","verb","note","age","addressed","pr"],Tr(t,e.chain).map(s=>xr(s,e.chain)),"no dispatches match")}var Sr={deck:"On deck",dispatches:"Dispatches",traps:"Traps",prs:"PRs",reports:"Reports",notices:"Notices"},Cr=["working","needs-decision","blocked","paused","done","failed","unknown"];function Dr(e,t){let s=t.daemonStale,n=e.daemon?[a`<span class=${s?"bad":"ok"}>${s&&"stale "}${v(e.daemon.heartbeat)} ago</span>`," ",a`<span class="dim">v${e.daemon.version}</span>`]:a`<span class="bad">down</span>`;return[a`<span class="chip">daemon ${n}</span>`,e.slots&&a`<span class="chip">active headless: ${e.slots.headless} of ${e.slots.limit}; traps: ${e.slots.traps}${e.slots.parked?`; parked: ${e.slots.parked} (no slot)`:""}</span>`,t.helms.map(({x:r,stale:i})=>a`<span key=${r.grounds} class="chip click" onClick=${w("helm",r.grounds)}>\u26F5 <b>${r.man}</b> <span class="dim">helm ${r.grounds}</span> <span class=${i?"warn":"ok"}>${i&&"stale "}${v(r.heartbeatAt)} ago</span></span>`)]}var xt=[];function Ar(e){let t=[...new Set([...e.dispatches.map(s=>s.repo),...e.notices.map(s=>s.repo),...e.prs.map(s=>s.repo)].filter(Boolean))].sort();return t.length!==xt.length&&(xt=t),xt}var Gt=[];function Rr(e){let t=[...new Set(e.notices.map(s=>s.kind))].sort();return t.length!==Gt.length&&(Gt=t),Gt}var be=e=>e.currentTarget.value;function Ir(e,t,s){let n=o=>t===o?"":"display:none",r=e?Ar(e):[],i=e?Rr(e):[];return a`<div class="controls">\n <select id="f-lane" style=${e&&n("dispatches")} value=${s.lane} onChange=${o=>L({lane:be(o)})}>\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=${s.repo} onChange=${o=>L({repo:be(o)})}>\n <option value="">all repos</option>\n ${r.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <select id="f-verb" style=${e&&n("dispatches")} value=${s.verb} onChange=${o=>L({verb:be(o)})}>\n <option value="">all verbs</option>\n ${Cr.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <label id="chain-control" style=${e&&n("dispatches")}><input id="f-chain" type="checkbox" checked=${!!s.chain} onChange=${o=>L({chain:o.currentTarget.checked})} /> group by chain</label>\n <select id="f-kind" style=${e&&n("notices")} value=${s.noticeKind} onChange=${o=>L({noticeKind:be(o)})}>\n <option value="">all notice kinds</option>\n ${i.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <input id="f-q" type="search" placeholder="search id \xB7 note \xB7 brief" value=${s.q} onInput=${o=>L({q:be(o)})} />\n </div>`}function _n({d:e,inp:t,tab:s,st:n,stale:r}){return[a`<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=${()=>C("settings","browser")}>\u2699</button></span></div>`,a`<div class="chips"><span id="chips" style="display:contents">${e&&t&&Dr(e,t.chips)}</span><span class="chip dim" id="clock">${e&&new Date(e.now).toLocaleTimeString("en-GB")}</span></div>`,a`<nav class="tabs" id="tabs" aria-label="Spyglass views">${le.map(i=>a`<a href=${"#"+i} data-tab=${i} class=${e?i===s?"on":"":void 0}>${Sr[i]}</a>`)}</nav>`,Ir(e,s,n)]}var $n=({d:e})=>e&&["\\u{1F99E}\\u2728 lobstah v"+e.version+" \\xB7 ",a`<a href=${e.repoUrl} target="_blank">${e.repoUrl.replace("https://github.com/","")}</a>`];function bn(e,t){if(!t.lobs)return[];let s={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready",landed:"landed",watch:"watch",report:"report"},n=t.hidden??{},r=e.filter(o=>!o.acked&&!(o.key!==void 0&&n[o.key]===o.stateHash)).map(o=>{let c=s[o.kind??""]??"",u=o.key!==void 0?{hideKey:o.key,hideHash:o.stateHash??""}:{};return o.kind==="decision"&&o.key?{key:"decision:"+o.key,text:o.note||o.verb,label:c,hash:is(o.key),...u}:typeof o.kind=="string"&&o.kind.startsWith("pr:")&&o.prUrl?{key:o.kind+":"+(o.key??o.prUrl),text:o.note||o.kind,href:o.prUrl,label:c,...u}:{key:(o.kind??"question")+":"+(o.key??o.lane+":"+o.id),text:o.note||o.verb,label:c,...o.kind==="watch"?{}:{open:o.kind==="report"&&o.key?ce(o.key):{type:"dispatch",key:o.lane+":"+o.id}},...u}});!r.length&&t.preview&&(r=[{key:"preview",text:"attention questions crawl in here",...t.previewHelm?{open:{type:"helm",key:t.previewHelm}}:{}}]);let i=r.length>4?r.length-4:0;return r=r.slice(0,4),i&&(r[3]={...r[3],text:"\\u2026and "+i+" more \\u2014 see attention",label:""}),r}var kn=!0;function Mr(e,t,s){let n="animation-duration:"+((innerWidth+180)/(100+t*12)).toFixed(1)+"s;animation-delay:-"+t*9%14+"s",r=()=>{e.hideKey&&Is(e.hideKey,e.hideHash??"")},i=[a`<div class="bub">${e.label&&[a`<span class="badge dim">${e.label}</span>`," "]}<span>${e.text.length>48?e.text.slice(0,47)+"\\u2026":e.text}</span></div>`,s===!1?a`<span class="fallback">\u{1F99E}</span>`:a`<div class="sprite"></div>`,kn&&a`<img\n class="star"\n src="/star.png"\n alt=""\n onError=${c=>{kn=!1,c.currentTarget.remove()}}\n />`],o=e.open;return e.hash?a`<a key=${e.key} class="lob" style=${n} title="open the decision" href=${e.hash} onClick=${r}>${i}</a>`:e.href?a`<a key=${e.key} class="lob" style=${n} title="open the PR" href=${e.href} target="_blank" rel="noopener" onClick=${r}>${i}</a>`:a`<div\n key=${e.key}\n class="lob"\n style=${n}\n title="click to open"\n onClick=${()=>{r(),o&&C(o.type,o.key)}}\n >\n ${i}\n </div>`}function yn({state:e}){let t=e.snapshot,s=bn(t?.attention||[],{lobs:e.prefs.lobs,hidden:e.lobHidden,preview:e.preview,previewHelm:t&&t.helms.length?t.helms[0].grounds:void 0}),n=s.map(r=>r.key).join("|")+(e.spriteOk===null?"?":e.spriteOk?"s":"e");return zs(()=>s.map((r,i)=>Mr(r,i,e.spriteOk)),[n])}function wn({box:e}){if(!e)return null;let t=s=>{s.target===s.currentTarget&&ue()};return a`<div id="lightbox" class="lightbox" role="dialog" aria-label=${e.name} onClick=${t}>\n <button type="button" class="lbclose" title="close" onClick=${ue}>\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 ne=a`<span class="x" onClick=${Z}>\xD7</span>`,Tn=(e,t,s)=>a`<span class="seg">${t.map(([n,r])=>a`<button class=${n===s?"on":""} onClick=${()=>e(n)}>${r}</button>`)}</span>`;function Pr(e,t){let s=Tn(As,[["table","table"],["cards","cards"]],t.view),n=Tn(Rs,[["on","on"],["off","off"]],t.lobs?"on":"off"),r=e.attentionError?e.attentionError:(e.attentionKinds||[]).join(" \\xB7 ");return[ne,a`<h3>\u2699 settings <span class="dim" style="font-weight:normal">\xB7 this browser only</span></h3>`,a`<div class="settings"><div class="row"><span class="lbl">view<span class="hint">cards or table (notices stay a table)</span></span>${s}</div><div class="row"><span class="lbl">lobs<span class="hint">crawling lobsters in this page</span></span>${n}</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 Er(e,t){let s=se(t.numbers,new Map(t.numbers.map((r,i)=>[r,t.titles[i]])),e.number),n=t.nextMergeable?[" \\xB7 ",a`<span class="ok">next mergeable</span>`]:t.blockedBy?" \\xB7 blocked by #"+t.blockedBy:t.nextNumber?" \\xB7 next is #"+t.nextNumber:"";return[s," \\xB7 ",t.position," of ",t.size," \\xB7 floor ",t.floor,n]}var Lr=e=>t=>{t.preventDefault(),C("dispatch",e)};function Nr(e,t){let s=us(e,t),n=s.pr,r=s.stack,i=s.watch,o=Be(n),c=s.chain.length?s.chain.flatMap((l,f)=>[f?" \\u2192 ":"",l.culled?a`<span class="dim">${l.id.slice(0,8)} (culled)</span>`:[a`<a href="#" onClick=${Lr(l.modalKey)}>${l.id.slice(0,8)}</a>`," ",a`<span class="dim">${l.verb}</span>`]]):a`<span class="dim">none</span>`,u=i?[a`<div>${i.key} \xB7 owner ${i.owner||"?"} \xB7 ${i.lastCheckedAt?["checked ",v(i.lastCheckedAt)," ago"]:"never checked"}</div>`,i.lastError&&a`<div class="bad">${i.lastError}</div>`,a`<div class="dim" style="font-size:11px;margin-top:4px">cursor</div>`,S(i.cursor)]:a`<div class="dim">no watch \u2014 <code>lobstah watch add ${n.url}</code> registers one</div>`;return[ne,a`<h3>${Oe(n)} ${n.title||""} <span class=${"badge "+E(n.badge)}>${n.badge.text}</span>${n.draft&&n.badge.text!=="draft"&&[" ",a`<span class="badge pr-draft">draft</span>`]}</h3>`,a`<div class="sub">${n.repo} \xB7 ${n.state} \xB7 observed ${v(n.observedAt)} ago${n.gate&&" \\xB7 gate "+n.gate}</div>`,a`<div class="sec">checks</div><div>${he(n)}</div><div class="sec">review</div><div>${o||a`<span class="dim">no review yet</span>`}</div><div class="sec">merge</div><div>${ge(n)}</div>${n.repairWait&&a`<div class="sec">repair waits</div><div>${n.repairWait.heldBy}: ${n.repairWait.reason}${n.repairWait.until?" \\xB7 until "+n.repairWait.until:""}</div>`}<div class="sec">refs</div><div>${n.headRefName||"?"} \u2192 ${n.baseRefName||"?"}</div><div class="sec">stack</div><div>${r?Er(n,r):a`<span class="dim">not stacked</span>`}</div><div class="sec">dispatch chain</div><div>${c}</div><div class="sec">watch</div>`,u]}var xn=(e,t)=>(e==="codex"?"codex resume ":"claude --resume ")+t;function Hr(e){let t=Date.now()-Date.parse(e.heartbeatAt)>18e5;return[ne,a`<h3>\u26F5 ${e.man}</h3><div class="sub">helm of <b>${e.grounds}</b> (${(e.repos||[]).join(", ")})</div><div class="sub">${e.harness??"?"} \xB7 ${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>`,e.sessionId&&[a`<div class="sec">open this session</div>`,S(xn(e.harness,e.sessionId))],e.transcript&&[a`<div class="sec">transcript</div>`,S(e.transcript)]]}function Or(e,t){return[ne,a`<h3>\u{1F4C4} ${e.title}</h3>`,a`<${Tt} r=${e} text=${t} />`]}function jr(e,t,s){let n=e.claimedBy&&e.claimedBy.startsWith("wt:")?[a`<div class="sec">worked by trap</div>`,a`<div class="claimedby">claimed by ${He(e.claimedBy.slice(3))}</div>`,S(O(e.claimedBy)),a`<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 ${O(e.claimedBy)} "\u2026"</div>`]:[a`<div class="sec">open this session</div>`,S("lobstah attach "+e.id)];return[ne,a`<h3>${e.id.slice(0,8)} <span class=${"badge v-"+e.verb}>${e.verb}</span></h3>`,a`<div class="sub">${e.repo} \xB7 ${e.lane} ${e.bucket} \xB7 ${v(e.verbAt)}${e.for&&[" \\xB7 ",me(e)]} ${te(e)}</div>`,n,e.worktree&&[a`<div class="sec">worktree${e.worktreeOf?" (reused from "+e.worktreeOf.slice(0,8)+")":""}</div>`,S(e.worktree),e.worktreeKept&&a`<div class="dim" style="font-size:11px">kept: ${e.worktreeKept}</div>`],e.transcript&&[a`<div class="sec">transcript</div>`,S(e.transcript)],t&&a`<${Tt} r=${t} text=${s} heading=${!0} />`,Ys(e)]}function Br(e){let t=ve(e),s=e.requested?[e.repo??""," \\xB7 ",e.harness??""," \\xB7 requested ",v(e.requested.at)," ago from the glass; the helm reserves it and starts its session."]: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.",n=e.notices.length?e.notices.map(o=>a`<div key=${o.seq} class="loglines">${v(o.at)} ago \xB7 <b>${o.kind}</b> \u2014 ${o.text}</div>`):a`<div class="empty">none recorded</div>`,r=e.messages.length?e.messages.map(o=>a`<div key=${o.file} class=${"msg"+(o.from==="helm"?" from-helm":"")}><div class="hdr">from ${o.from} \xB7 ${o.at&&[v(o.at)," ago"]} \xB7 ${o.state==="pending"?a`<span class="warn">pending</span>`:a`<span class="ok">delivered</span>`}</div>${o.text}${o.attachments?.length?ee(o.attachments,c=>os(e.trapId,c)):""}</div>`):a`<div class="empty">none</div>`,i=e.catches.length?e.catches.map(o=>a`<div key=${o.lane+":"+o.id} class="catch"><div class="hdr"><b>${o.id.slice(0,8)}</b><span class=${"badge v-"+o.verb}>${o.verb}</span><span class="dim">${v(o.verbAt)}</span>${te(o)}</div><div class="loglines">${mt(o)}</div></div>`):a`<div class="empty">none yet</div>`;return[ne,a`<h3>\u{1FAA4} ${e.label??`wt:${e.trapId}`} <span class="badge">${e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??"signed off"}</span></h3>`,e.worktree&&a`<div class="sub">${e.worktree}</div>`,a`<div class="sub">${s}</div>`,a`<div class="sec">window</div>`,K(e),z(e),e.live&&e.sessionId&&[a`<div class="sec">open this session</div>`,S(xn(e.harness,e.sessionId)),a`<div class="dim" style="font-size:11px">as registered at sign-on \u2014 a hookless enlistment may hold a made-up id</div>`],a`<div class="sec">lifecycle (${e.notices.length})</div>`,n,a`<div class="sec">messages (${e.messages.length})</div>`,r,a`<div class="sec">catches (${e.catches.length})</div>`,i]}function Gn({snapshot:e,modal:t,prefs:s,reportText:n}){if(!e||!t)return null;let r=Q(e,t);if(!r)return null;if(t.type==="settings")return Pr(r,s);if(t.type==="pr")return Nr(e,t.key);if(t.type==="helm")return Hr(r);if(t.type==="report")return Or(r,n[t.key]);if(t.type==="dispatch"){let i=cs(e,r);return jr(r,i,i&&n[i.key])}return Br(r)}var Ur=e=>a`<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>`,Sn=({inp:e})=>R(["at","kind","text","repo"],e.list.map(Ur),"no notices");function Cn(e){let t=new Map;for(let s of e.prs){let n=t.get(s.stackId)||[];n.push(s),t.set(s.stackId,n)}return e.stacks.map(s=>({s,prs:t.get(s.id)||[]})).filter(s=>s.prs.length)}var Dn=(e,t)=>se(e.numbers,new Map(t.map(s=>[s.number,s.title]))),St=e=>e.state+(e.draft?" \\xB7 draft":"")+(e.state==="MERGED"&&e.mergedAt?" \\xB7 "+e.mergedAt:"");function An(e){let t=n=>{let r=String(n??"");return r.length>24?r.slice(0,23)+"\\u2026":r},s=e.watches.map(n=>a`<tr key=${n.key}><td>${n.key}</td><td>${n.owner}</td><td title=${n.cursor}>${t(n.cursor)}</td><td>${n.lastCheckedAt&&v(n.lastCheckedAt)}</td><td>${n.lastError||""}</td></tr>`);return[a`<h2>other watches</h2>`,R(["key","owner","cursor","last check","error"],s,"no other watches")]}function Fr(e){let t=Cn(e).flatMap(({s,prs:n})=>[a`<tr key=${"stack:"+s.id}><th colspan="8">${Dn(s,n)} \xB7 floor ${s.floor}${s.open?" \\xB7 open":" \\xB7 history"}</th></tr>`,...n.map(r=>a`<tr key=${r.key} class="rowhead" onClick=${w("pr",r.key)}><td>${Oe(r)}</td><td class="grow">${r.title||""}</td><td>${St(r)}</td><td>${he(r)}</td><td>${Be(r)}</td><td>${ge(r)}</td><td>${gt(r.watch)}</td><td>${r.gate||""}</td></tr>`)]);return[R(["PR","title","state","checks","review","merge","watch","gate"],t,"no PR evidence"),An(e)]}function qr(e){let t=Cn(e),s=r=>a`<div key=${r.key} class="card" onClick=${w("pr",r.key)}><div class="top">${je(r)}<span class=${"badge "+E(r.badge)+H(r.badge.text)} title=${N(r.badge.text)}>${r.badge.text}</span></div><div class="meta" title=${`${r.repo} \\xB7 ${St(r)}`}>${r.repo} \xB7 ${St(r)} \xB7 ${ge(r)}</div><div class="foot"><span>${he(r)}</span><span>${gt(r.watch)}</span>${r.gate&&a`<span>gate ${r.gate}</span>`}</div></div>`;return[t.length?t.map(({s:r,prs:i})=>a`<${J} key=${"stack:"+r.id}><h2>${Dn(r,i)} \xB7 floor ${r.floor}${r.open?"":" \\xB7 history"}</h2><div class="cards">${i.map(s)}</div><//>`):a`<div class="empty">no PR evidence</div>`,An(e)]}var Rn=({inp:e})=>e.view==="cards"?qr(e):Fr(e);var Ct=e=>e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??(e.live?"":"signed off"),In=e=>e.live||e.starting?"":" dim";function Wr(e){let t=ve(e);return a`<tr key=${e.trapId} class=${"rowhead"+In(e)} onClick=${w("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??""}</td><td>${(e.sessionId??"").slice(0,8)}</td><td>${_e(e)}${z(e)}</td><td>${t.listen}</td><td>${t.hb}</td><td>${_t(e)}</td><td>${e.catches.length}</td><td>${K(e)}</td></tr>`}function Vr(e){let t=ve(e),s=_t(e),n=`${e.repo??(e.live?"addressed bait only":"history")}${e.sessionId?" \\xB7 session "+e.sessionId.slice(0,8):""}`;return a`<div key=${e.trapId} class=${"card"+In(e)} onClick=${w("trap",e.trapId)}><div class="top"><b>\u{1FAA4} ${e.label??`wt:${e.trapId}`}</b><span class=${"badge"+H(Ct(e))} title=${N(Ct(e))}>${Ct(e)}</span></div><div class="meta" title=${n}>${n}</div>${e.worktree&&a`<div class="note" title=${e.worktree}>${e.worktree}</div>`}<div class="note" title=${Fe(e)}>${_e(e)}</div>${z(e)}<div class="foot"><span>${t.listen}${e.live&&[" \\xB7 heartbeat ",t.hb]} \xB7 ${e.catches.length} catch${e.catches.length===1?"":"es"}${s&&[" \\xB7 ",s]}</span><span class="footact">${K(e)}</span></div></div>`}function Mn({inp:e}){let t=e.list.map(n=>n.x),s=a`<div class="tabhead"><${Ue} /></div>`;return e.view==="cards"?[s,t.length?a`<div class="cards">${t.map(Vr)}</div>`:a`<div class="empty">no traps soaking</div>`]:[s,R(["address","repo","worktree","harness","session","now","listening","heartbeat","mail","catches","window"],t.map(Wr),"no traps soaking")]}function Pn({state:e}){let t=e.snapshot,s=e.route,n=t&&ps(t,{st:e.prefs,modal:e.modal},Date.now()),r=o=>!n||o!==s?null:o==="deck"?a`<${gn} inp=${n.deck} drafts=${e.drafts} focus=${e.focusDecision} extensions=${t?.answerLimits?.extensions??[]} />`:o==="dispatches"?a`<${vn} inp=${n.dispatches} />`:o==="traps"?a`<${Mn} inp=${n.traps} />`:o==="prs"?a`<${Rn} inp=${n.prs} />`:o==="reports"?a`<${rn} inp=${n.reports} />`:a`<${Sn} inp=${n.notices} />`,i=o=>{o.target===o.currentTarget&&Z()};return[a`<${_n} d=${t} inp=${n} tab=${s} st=${e.prefs} stale=${e.stale} />`,le.map(o=>a`<main key=${o} id=${"page-"+o} class=${t&&o===s?"tabpage on":"tabpage"}><div id=${o}>${r(o)}</div></main>`),a`<footer id="foot"><${$n} d=${t} /></footer>`,a`<div id="lobs"><${yn} state=${e} /></div>`,a`<${wn} box=${e.lightbox} />`,a`<div id="overlay" class=${e.modal&&t?"open":t?"":void 0} onClick=${i}><div class="modal" id="modalbox"><${Gn} snapshot=${t} modal=${e.modal} prefs=${e.prefs} reportText=${e.reportText} /></div></div>`]}var Dt=!1,ke=null;async function At(){if(!Dt){Dt=!0;try{let e=await fetch("/data");if(!e.ok)throw new Error(`/data answered ${e.status}`);lt(await e.json())}catch{Gs()}finally{Dt=!1}}}var En=()=>{ke||(ke=setInterval(At,2e3))},Kr=()=>{ke&&clearInterval(ke),ke=null};function Ln(){document.addEventListener("visibilitychange",()=>{document.hidden?Kr():(At(),En())}),At(),document.hidden||En()}var Rt=()=>ns(location.hash),It=()=>rs(location.hash),Nn=e=>window.addEventListener("hashchange",()=>e(Rt()));$s({snapshot:void 0,route:Rt(),prefs:ms(),modal:It(),stale:!1,lobHidden:gs(),spriteOk:null,focusResults:{},preview:new URLSearchParams(location.search).has("lob"),reportText:{},drafts:{},focusDecision:nt(location.hash),lightbox:null});var Hn,Mt=!1,On=()=>{let e=_(),t=e.route!==Hn||!Mt&&!!e.snapshot;Zt(ae(Pn,{state:e}),document.body),Hn=e.route,Mt||(Mt=!!e.snapshot),t&&window.scrollTo(0,0),zr(e.focusDecision)},Pt=null;function zr(e){if(!e||e===Pt)return;let t=[...document.querySelectorAll("[data-decision]")].find(s=>s.getAttribute("data-decision")===e);t&&(Pt=e,t.scrollIntoView?.({block:"center"}))}bs(On);On();var Et=new Image;Et.onload=()=>G({spriteOk:!0});Et.onerror=()=>G({spriteOk:!1});Et.src="/lob-sprite.png";Nn(e=>{let t=It(),s=nt(location.hash);s!==_().focusDecision&&(Pt=null),G(t?{route:e,modal:t,focusDecision:s}:{route:e,focusDecision:s}),t&&Ie()});document.addEventListener("keydown",e=>{e.key==="Escape"&&(_().lightbox?ue():Z())});Ln();})();</script>\n </body>\n</html>\n';
|
|
13273
|
+
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;--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}*{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}.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)}.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}.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}#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:10;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 .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 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}.lob .sprite{width:72px;height:56px;background:url(/lob-sprite.png) 0 0 no-repeat;background-size:400% 100%;image-rendering:pixelated;animation:step 0.5s steps(4) infinite}.lob .fallback{display:inline-block;animation:waddle 0.45s ease-in-out infinite alternate}.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}.lob .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}}@keyframes waddle{from{transform:rotate(-8deg) translateY(0)}to{transform:rotate(8deg) translateY(-3px)}}#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}.dcards{display:flex;flex-direction:column;gap:10px}.dcard{width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--card-radius);padding:var(--card-pad)}.dcard.focus{animation:dflash 1.6s ease-out 1}@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}}.dcard.answered{opacity:0.7}.dcard .dtop{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2)}.dcard .dtop .badge{margin-top:0}.dcard .dtitle{white-space:pre-wrap;overflow-wrap:anywhere}.dcard .dmeta{font-size:11px;margin-left:auto}.dcard .dlink{color:var(--link)}.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}.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;overflow-x:auto;white-space:pre}.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{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}.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{max-width:1100px;margin:0 auto;padding:20px 16px 48px}.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}</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 Ae,b,Bt,Bs,O,Nt,Ot,qt,Je,Ge,le,Ft,Ze,Xe,Qe,Os,Se={},Ce=[],qs=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Re=Array.isArray;function E(e,t){for(var n in t)e[n]=t[n];return e}function Ye(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Q(e,t,n){var s,r,i,o={};for(i in t)i=="key"?s=t[i]:i=="ref"?r=t[i]:o[i]=t[i];if(arguments.length>2&&(o.children=arguments.length>3?Ae.call(arguments,2):n),typeof e=="function"&&e.defaultProps!=null)for(i in e.defaultProps)o[i]===void 0&&(o[i]=e.defaultProps[i]);return xe(e,o,s,r,null)}function xe(e,t,n,s,r){var i={type:e,props:t,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++Bt,__i:-1,__u:0};return r==null&&b.vnode!=null&&b.vnode(i),i}function Z(e){return e.children}function Te(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 Fs(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,s=[],r=[],i=E({},t);i.__v=t.__v+1,b.vnode&&b.vnode(i),et(e.__P,i,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,s,n??V(t),!!(32&t.__u),r),i.__v=t.__v,i.__.__k[i.__i]=i,Jt(s,i,r),t.__e=t.__=null,i.__e!=n&&Wt(i)}}function Wt(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}),Wt(e)}function Ht(e){(!e.__d&&(e.__d=!0)&&O.push(e)&&!De.__r++||Nt!=b.debounceRendering)&&((Nt=b.debounceRendering)||Ot)(De)}function De(){try{for(var e,t=1;O.length;)O.length>t&&O.sort(qt),e=O.shift(),t=O.length,Fs(e)}finally{O.length=De.__r=0}}function Vt(e,t,n,s,r,i,o,c,u,l,f){var h,d,m,p,g,x,G=s&&s.__k||Ce,$=t.length;for(u=Ws(n,t,G,u,$),h=0;h<$;h++)(m=n.__k[h])!=null&&(d=m.__i!=-1&&G[m.__i]||Se,m.__i=h,x=et(e,m,d,r,i,o,c,u,l,f),p=m.__e,m.ref&&d.ref!=m.ref&&(d.ref&&tt(d.ref,null,m),f.push(m.ref,m.__c||p,m)),g==null&&p!=null&&(g=p),4&m.__u?(u=Kt(m,u,e),d.__e&&(d.__e=null)):typeof m.type=="function"&&x!==void 0?u=x:p&&(u=p.nextSibling),m.__u&=-7);return n.__e=g,u}function Ws(e,t,n,s,r){var i,o,c,u,l,f=n.length,h=f,d=0;for(e.__k=new Array(r),i=0;i<r;i++)(o=t[i])!=null&&typeof o!="boolean"&&typeof o!="function"?(typeof o=="string"||typeof o=="number"||typeof o=="bigint"||o.constructor==String?o=e.__k[i]=xe(null,o,null,null,null):Re(o)?o=e.__k[i]=xe(Z,{children:o},null,null,null):o.constructor===void 0&&o.__b>0?o=e.__k[i]=xe(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):e.__k[i]=o,u=i+d,o.__=e,o.__b=e.__b+1,c=null,(l=o.__i=Vs(o,n,u,h))!=-1&&(h--,(c=n[l])&&(c.__u|=2)),c==null||c.__v==null?(l==-1&&(r>f?d--:r<f&&d++),typeof o.type!="function"&&(o.__u|=4)):l!=u&&(l==u-1?d--:l==u+1?d++:(l>u?d--:d++,o.__u|=4))):e.__k[i]=null;if(h)for(i=0;i<f;i++)(c=n[i])!=null&&(2&c.__u)==0&&(c.__e==s&&(s=V(c)),Qt(c,c));return s}function Kt(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=Kt(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 Vs(e,t,n,s){var r,i,o,c=e.key,u=e.type,l=t[n],f=l!=null&&(2&l.__u)==0;if(l===null&&c==null||f&&c==l.key&&u==l.type)return n;if(s>(f?1:0)){for(r=n-1,i=n+1;r>=0||i<t.length;)if((l=t[o=r>=0?r--:i++])!=null&&(2&l.__u)==0&&c==l.key&&u==l.type)return o}return-1}function Ut(e,t,n){t[0]=="-"?e.setProperty(t,n??""):e[t]=n==null?"":typeof n!="number"||qs.test(t)?n:n+"px"}function we(e,t,n,s,r){var i,o;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||Ut(e.style,t,"");if(n)for(t in n)s&&n[t]==s[t]||Ut(e.style,t,n[t])}else if(t[0]=="o"&&t[1]=="n")i=t!=(t=t.replace(Ft,"$1")),o=t.toLowerCase(),t=o in e||t=="onFocusOut"||t=="onFocusIn"?o.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=n,n?s?n[le]=s[le]:(n[le]=Ze,e.addEventListener(t,i?Qe:Xe,i)):e.removeEventListener(t,i?Qe:Xe,i);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 jt(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[Ge]==null)t[Ge]=Ze++;else if(t[Ge]<n[le])return;return n(b.event?b.event(t):t)}}}function et(e,t,n,s,r,i,o,c,u,l){var f,h,d,m,p,g,x,G,$,P,ie,W,ae,Lt,ye,ze,I=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(u=!!(32&n.__u),i=[c=t.__e=n.__e]),(f=b.__b)&&f(t);e:if(typeof I=="function"){h=o.length;try{if($=t.props,P=I.prototype&&I.prototype.render,ie=(f=I.contextType)&&s[f.__c],W=f?ie?ie.props.value:f.__:s,n.__c?G=(d=t.__c=n.__c).__=d.__E:(P?t.__c=d=new I($,W):(t.__c=d=new Te($,W),d.constructor=I,d.render=zs),ie&&ie.sub(d),d.state||(d.state={}),d.__n=s,m=d.__d=!0,d.__h=[],d._sb=[]),P&&d.__s==null&&(d.__s=d.state),P&&I.getDerivedStateFromProps!=null&&(d.__s==d.state&&(d.__s=E({},d.__s)),E(d.__s,I.getDerivedStateFromProps($,d.__s))),p=d.props,g=d.state,d.__v=t,m)P&&I.getDerivedStateFromProps==null&&d.componentWillMount!=null&&d.componentWillMount(),P&&d.componentDidMount!=null&&d.__h.push(d.componentDidMount);else{if(P&&I.getDerivedStateFromProps==null&&$!==p&&d.componentWillReceiveProps!=null&&d.componentWillReceiveProps($,W),t.__v==n.__v||!d.__e&&d.shouldComponentUpdate!=null&&d.shouldComponentUpdate($,d.__s,W)===!1){t.__v!=n.__v&&(d.props=$,d.state=d.__s,d.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(X){X&&(X.__=t)}),Ce.push.apply(d.__h,d._sb),d._sb=[],d.__h.length&&o.push(d),c=V(n);break e}d.componentWillUpdate!=null&&d.componentWillUpdate($,d.__s,W),P&&d.componentDidUpdate!=null&&d.__h.push(function(){d.componentDidUpdate(p,g,x)})}if(d.context=W,d.props=$,d.__P=e,d.__e=!1,ae=b.__r,Lt=0,P)d.state=d.__s,d.__d=!1,ae&&ae(t),f=d.render(d.props,d.state,d.context),Ce.push.apply(d.__h,d._sb),d._sb=[];else do d.__d=!1,ae&&ae(t),f=d.render(d.props,d.state,d.context),d.state=d.__s;while(d.__d&&++Lt<25);d.state=d.__s,d.getChildContext!=null&&(s=E(E({},s),d.getChildContext())),P&&!m&&d.getSnapshotBeforeUpdate!=null&&(x=d.getSnapshotBeforeUpdate(p,g)),ye=f!=null&&f.type===Z&&f.key==null?Xt(f.props.children):f,c=Vt(e,Re(ye)?ye:[ye],t,n,s,r,i,o,c,u,l),d.base=t.__e,t.__u&=-161,d.__h.length&&o.push(d),G&&(d.__E=d.__=null)}catch(X){if(o.length=h,t.__v=null,u||i!=null){if(X.then){for(t.__u|=u?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;i!=null&&(i[i.indexOf(c)]=null),t.__e=c}else if(i!=null)for(ze=i.length;ze--;)Ye(i[ze])}else t.__e=n.__e;t.__k==null&&(t.__k=n.__k||[]),X.then||zt(t),b.__e(X,t,n)}}else i==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):c=t.__e=Ks(n.__e,t,n,s,r,i,o,u,l);return(f=b.diffed)&&f(t),128&t.__u?void 0:c}function zt(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(zt))}function Jt(e,t,n){for(var s=0;s<n.length;s++)tt(n[s],n[++s],n[++s]);b.__c&&b.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(i){i.call(r)})}catch(i){b.__e(i,r.__v)}})}function Xt(e){return typeof e!="object"||e==null||e.__b>0?e:Re(e)?e.map(Xt):e.constructor!==void 0?null:E({},e)}function Ks(e,t,n,s,r,i,o,c,u){var l,f,h,d,m,p,g,x=n.props||Se,G=t.props,$=t.type;if($=="svg"?r="http://www.w3.org/2000/svg":$=="math"?r="http://www.w3.org/1998/Math/MathML":r||(r="http://www.w3.org/1999/xhtml"),i!=null){for(l=0;l<i.length;l++)if((m=i[l])&&"setAttribute"in m==!!$&&($?m.localName==$:m.nodeType==3)){e=m,i[l]=null;break}}if(e==null){if($==null)return document.createTextNode(G);e=document.createElementNS(r,$,G.is&&G),c&&(b.__m&&b.__m(t,i),c=!1),i=null}if($==null)x===G||c&&e.data==G||(e.data=G);else{if(i=$=="textarea"&&G.defaultValue!=null?null:i&&Ae.call(e.childNodes),!c&&i!=null)for(x={},l=0;l<e.attributes.length;l++)x[(m=e.attributes[l]).name]=m.value;for(l in x)m=x[l],l=="dangerouslySetInnerHTML"?h=m:l=="children"||l in G||l=="value"&&"defaultValue"in G||l=="checked"&&"defaultChecked"in G||we(e,l,null,m,r);for(l in G)m=G[l],l=="children"?d=m:l=="dangerouslySetInnerHTML"?f=m:l=="value"?p=m:l=="checked"?g=m:c&&typeof m!="function"||x[l]===m||we(e,l,m,x[l],r);if(f)c||h&&(f.__html==h.__html||f.__html==e.innerHTML)||(e.innerHTML=f.__html),t.__k=[];else if(h&&(e.innerHTML=""),Vt(t.type=="template"?e.content:e,Re(d)?d:[d],t,n,s,$=="foreignObject"?"http://www.w3.org/1999/xhtml":r,i,o,i?i[0]:n.__k&&V(n,0),c,u),i!=null)for(l=i.length;l--;)Ye(i[l]);c&&$!="textarea"||(l="value",$=="progress"&&p==null?e.removeAttribute("value"):p!=null&&(p!==e[l]||$=="progress"&&!p||$=="option"&&p!=x[l])&&we(e,l,p,x[l],r),l="checked",g!=null&&g!=e[l]&&we(e,l,g,x[l],r))}return e}function tt(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){b.__e(r,n)}}function Qt(e,t,n){var s,r;if(b.unmount&&b.unmount(e),(s=e.ref)&&(s.current&&s.current!=e.__e||tt(s,null,t)),(s=e.__c)!=null){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(i){b.__e(i,t)}s.base=s.__P=s.__n=null}if(s=e.__k)for(r=0;r<s.length;r++)s[r]&&Qt(s[r],t,n||typeof e.type!="function");n||Ye(e.__e),e.__c=e.__=e.__e=void 0}function zs(e,t,n){return this.constructor(e,n)}function nt(e,t,n){var s,r,i,o;t==document&&(t=document.documentElement),b.__&&b.__(e,t),r=(s=typeof n=="function")?null:n&&n.__k||t.__k,i=[],o=[],et(t,e=(!s&&n||t).__k=Q(Z,null,[e]),r||Se,Se,t.namespaceURI,!s&&n?[n]:r?null:t.firstChild?Ae.call(t.childNodes):null,i,!s&&n?n:r?r.__e:t.firstChild,s,o),Jt(i,e,o),e.props.children=null}Ae=Ce.slice,b={__e:function(e,t,n,s){for(var r,i,o;t=t.__;)if((r=t.__c)&&!r.__)try{if((i=r.constructor)&&i.getDerivedStateFromError!=null&&(r.setState(i.getDerivedStateFromError(e)),o=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,s||{}),o=r.__d),o)return r.__E=r}catch(c){e=c}throw e}},Bt=0,Bs=function(e){return e!=null&&e.constructor===void 0},Te.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=E({},this.state),typeof e=="function"&&(e=e(E({},n),this.props)),e&&E(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),Ht(this))},Te.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),Ht(this))},Te.prototype.render=Z,O=[],Ot=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,qt=function(e,t){return e.__v.__b-t.__v.__b},De.__r=0,Je=Math.random().toString(8),Ge="__d"+Je,le="__a"+Je,Ft=/(PointerCapture)$|Capture$/i,Ze=0,Xe=jt(!1),Qe=jt(!0),Os=0;function Js(e){return{id:e,lane:"work",bucket:"done",repo:"",brief:"",attachments:[],messageAttachments:[],verb:"unknown",log:[],inbox:[],sort:0}}var Zt=new WeakMap;function st(e,t){let n=e.dispatches||[],s=Zt.get(n);return s||Zt.set(n,s=new Map(n.map(r=>[r.id,r]))),{...t,catches:(t.catches||[]).map(r=>s.get(r)??Js(r))}}function L(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 ce=["deck","dispatches","traps","prs","reports","notices"];function nn(e){let t=String(e||"").replace(/^#/,"");return ce.includes(t)?t:"deck"}var rt=e=>`#decision/${encodeURIComponent(e)}`;function ot(e){let t=/^#?decision\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var it=(e,t,n)=>`/attachment/dispatch/${encodeURIComponent(e)}/${encodeURIComponent(t)}/${encodeURIComponent(n)}`,sn=(e,t)=>`/attachment/trap/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,rn=e=>/\\.(png|jpe?g|gif|webp)$/i.test(e),at=(e,t)=>`/decision/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function lt(e,t){let n=new Map(t.map(r=>[r.key,r])),s=[];for(let r of e)if(r.kind==="decision"){let i=n.get(r.key);if(!i)continue;s.push({kind:"decision",key:i.key,title:i.title,detail:i.detail,options:i.options,attachments:i.attachments,...i.dispatch?{dispatch:i.dispatch,lane:i.lane??"work"}:{},...i.repo?{repo:i.repo}:{},at:i.askedAt})}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??""});return s.sort((r,i)=>i.at.localeCompare(r.at)||r.key.localeCompare(i.key))}function on(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 an(e,t){return(e.reports||[]).find(n=>n.key===`report:${t.lane}:${t.id}`)}function de(e){return e.author==="helm"?"":e.trap?e.trap:e.author==="headless"?e.dispatch?e.dispatch.slice(0,8):"":e.author}var Yt=(e,t)=>+!!e.acked-+!!t.acked||t.filedAt.localeCompare(e.filedAt),C=e=>`/report/${encodeURIComponent(e)}`;function ln(e){let t=/^#?report\\/(.+)$/.exec(String(e||""));if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}function cn(e){let t=/^\\/report\\/([^/?#]+)\\/?$/.exec(e);if(!t)return null;try{return decodeURIComponent(t[1])}catch{return null}}var dn=e=>`/report/${encodeURIComponent(e)}/md`,ct=(e,t)=>`/report/${encodeURIComponent(e)}/files/${encodeURIComponent(t)}`;function en(e,t,n){return!!e&&n-Date.parse(e)>t}function tn(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.brief||"")+" "+(e.repo||"")+" "+(e.for||"")).toLowerCase().includes(n))return!1}return!0}function Y(e,t){if(!t)return null;if(t.type==="helm")return e.helms.find(s=>s.grounds===t.key)||null;if(t.type==="dispatch")return e.dispatches.find(s=>s.lane+":"+s.id===t.key)||null;if(t.type==="pr")return(e.prs||[]).find(s=>s.key===t.key)||null;if(t.type==="settings")return{attentionKinds:e.attentionKinds||[],attentionError:e.attentionError};let n=e.traps.find(s=>s.trapId===t.key);return n?st(e,n):null}function pn(e,t,n){let s=t.st,r=String(s.q||"").toLowerCase(),i=(...p)=>!r||p.join(" ").toLowerCase().includes(r),o=p=>({x:p,stale:en(p.heartbeatAt,18e5,n)}),c=Y(e,t.modal),u=(p,g)=>!!p&&n-Date.parse(p)<=g,l=p=>Math.max(0,...(p.notices||[]).filter(g=>g.kind==="trap-stowed"||g.kind==="trap-ghosted").map(g=>Date.parse(g.at)||0)),f=p=>p.live||!!p.starting||!!p.requested,h=[...e.traps||[]].sort((p,g)=>Number(f(g))-Number(f(p))||Number(g.live)-Number(p.live)||(p.live?(Date.parse(p.signedOnAt||"")||0)-(Date.parse(g.signedOnAt||"")||0):l(g)-l(p))||(p.name??p.trapId).localeCompare(g.name??g.trapId)),d=h.filter(p=>(f(p)||(p.notices||[]).some(g=>(g.kind==="trap-stowed"||g.kind==="trap-ghosted")&&u(g.at,36e5)))&&i(p.name,p.trapId,p.repo,p.worktree)),m=({ageSecs:p,...g})=>g;return{chips:{daemon:e.daemon,daemonStale:!!e.daemon&&en(e.daemon.heartbeat,9e4,n),helms:e.helms.map(o)},deck:{view:s.view,decisions:lt(e.attention||[],e.decisions||[]).filter(p=>p.kind==="decision"?i(p.kind,p.repo,p.title,p.dispatch,p.detail):i(p.kind,p.repo,p.note,p.dispatch)),prAttention:(e.attention||[]).filter(p=>p.kind&&p.kind.startsWith("pr:")).map(m),landed:(e.landed||[]).filter(p=>u(p.at,864e5)&&i(p.repo,p.note,p.id)).sort((p,g)=>Date.parse(g.at)-Date.parse(p.at)).slice(0,8),reports:(e.reports||[]).filter(p=>i(p.title,p.author,p.dispatch,p.repo)).sort(Yt),inflight:e.dispatches.filter(p=>p.bucket!=="done"&&tn(p,{...s,lane:"",repo:"",verb:""})),traps:d.map(p=>o(st(e,p))),stacks:(e.stacks||[]).filter(p=>p.open&&i(p.repo,p.numbers.join(" "))),prs:(e.prs||[]).filter(p=>p.state==="OPEN"),error:e.attentionError},dispatches:{view:s.view,chain:s.chain,list:e.dispatches.filter(p=>tn(p,s))},traps:{view:s.view,list:h.filter(p=>(!s.repo||p.repo===s.repo)&&i(p.name,p.trapId,p.repo,p.worktree,p.harness)).map(p=>o(st(e,p)))},prs:{view:s.view,stacks:(e.stacks||[]).filter(p=>!s.repo||p.repo===s.repo),prs:(e.prs||[]).filter(p=>(!s.repo||p.repo===s.repo)&&i(p.number,p.title,p.url,p.state,p.baseRefName,p.headRefName)),watches:(e.watches||[]).filter(p=>!String(p.key).startsWith("pr:"))},reports:{view:s.view,list:(e.reports||[]).filter(p=>(!s.repo||p.repo===s.repo)&&i(p.title,p.author,p.dispatch,p.repo)).sort(Yt)},notices:{list:(e.notices||[]).filter(p=>(!s.repo||!p.repo||p.repo===s.repo)&&(!s.noticeKind||p.kind===s.noticeKind)&&i(p.kind,p.text,p.repo))},foot:{version:e.version,repoUrl:e.repoUrl},modal:{modal:t.modal,item:c&&o(c),prefs:t.modal&&t.modal.type==="settings"?{view:s.view,lobs:s.lobs}:void 0}}}function un(e,t){let n=(e.prs||[]).find(c=>c.key===t);if(!n)return null;let s=(e.stacks||[]).find(c=>c.id===n.stackId),r=new Map((e.dispatches||[]).map(c=>[c.id,c])),i=(n.dispatchIds||[]).map(c=>{let u=r.get(c);return u?{id:c,verb:u.verb,modalKey:u.lane+":"+u.id}:{id:c,culled:!0}}),o=n.watch;return{pr:n,stack:s?{numbers:s.numbers,titles:s.numbers.map(c=>(e.prs||[]).find(u=>u.stackId===s.id&&u.number===c)?.title||""),position:n.position+1,size:s.numbers.length,floor:s.floor,nextNumber:s.nextNumber,nextMergeable:!!n.nextMergeable,blockedBy:n.blockedBy}:null,chain:i,watch:o?{key:o.key,owner:o.owner||"",lastCheckedAt:o.lastCheckedAt||null,lastError:o.lastError||null,cursor:o.cursor}:null}}function fn(e){return e?{text:e.lastError?"failing":"watching",at:e.lastCheckedAt||null}:{text:"no watch",at:null}}function mn(){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 hn(e){try{localStorage.setItem("spyglass",JSON.stringify(e))}catch{}}function gn(){try{return JSON.parse(localStorage.getItem("spyglass-lob-hidden")||"{}")||{}}catch{return{}}}function vn(e){try{localStorage.setItem("spyglass-lob-hidden",JSON.stringify(e))}catch{}}var pe,_n=new Set,_=()=>pe;function dt(e){pe=e}function T(e){pe={...pe,...e};for(let t of _n)t(pe)}var pt=e=>{_n.add(e)};function ut(e){let{modal:t,drafts:n}=_(),s=new Set(lt(e.attention||[],e.decisions||[]).map(i=>i.key)),r=Object.fromEntries(Object.entries(n).filter(([i])=>s.has(i)));T({snapshot:e,stale:!1,modal:t&&Y(e,t)?t:null,...Object.keys(r).length!==Object.keys(n).length?{drafts:r}:{}})}var $n=()=>({text:"",files:[]});function A(e,t){let n=_().drafts;T({drafts:{...n,[e]:{...n[e]??$n(),...t}}})}function bn(e,t){let n=_().drafts[e]?.option;A(e,{option:n===t?void 0:t,error:void 0})}var Xs=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 ft(e,t){let n=_().snapshot?.answerLimits,s=[...t??[]],r=_().drafts[e]?.files??[],i=[],o=[];for(let c of s){let u=(/\\.[^.]+$/.exec(c.name)?.[0]??"").toLowerCase();if(n&&!n.extensions.includes(u))i.push(`${c.name}: type not accepted`);else if(n&&c.size>n.maxBytes)i.push(`${c.name}: larger than ${n.maxBytes} bytes`);else if(n&&r.length+o.length>=n.maxFiles)i.push(`${c.name}: at most ${n.maxFiles} files`);else try{o.push({name:c.name,bytes:c.size,data:await Xs(c)})}catch{i.push(`${c.name}: could not be read`)}}A(e,{files:[..._().drafts[e]?.files??[],...o],error:i.length?i.join("; "):void 0})}var Qs={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};async function kn(e,t){let n=[...t.clipboardData?.items??[]],s=new Date().toISOString().replace(/[:.]/g,"-").replace(/-\\d{3}Z$/,"Z"),r=n.filter(i=>i.kind==="file"&&i.type.startsWith("image/")).map(i=>i.getAsFile()).filter(i=>i!==null).map((i,o,c)=>{let u=`pasted-${s}${c.length>1?`-${o+1}`:""}${Qs[i.type]??".png"}`;return new File([i],u,{type:i.type})});r.length&&await ft(e,r)}function yn(e,t){let n=(_().drafts[e]?.files??[]).filter((s,r)=>r!==t);A(e,{files:n})}async function wn(e){let t=_().snapshot?.focusToken,n=_().drafts[e]??$n();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(i=>({name:i.name,data:i.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:on({option:n.option,text:n.text,files:n.files.length})})}catch{A(e,{sending:!1,error:"The answer could not be sent."})}}}var Gn=()=>T({stale:!0}),xn=(e,t)=>T({lightbox:{src:e,name:t}}),ee=()=>T({lightbox:null});function M(e,t){let{snapshot:n}=_(),s={type:e,key:t};T({modal:!n||Y(n,s)?s:null})}function te(){T({modal:null})}async function Tn(e){let t=_().snapshot?.focusToken;if(t)try{let s=await(await fetch(`/api/focus/${encodeURIComponent(e)}`,{method:"POST",headers:{"x-lobstah-focus-token":t}})).json();T({focusResults:{..._().focusResults,[e]:s.message??s.reason??"Window focus failed."}})}catch{T({focusResults:{..._().focusResults,[e]:"Window focus failed."}})}}async function Sn(e,t){let n=_().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{ut(await(await fetch("/data")).json())}catch{}}function N(e){let t={..._().prefs,...e};hn(t),T({prefs:t})}function Cn(e){e!=="table"&&e!=="cards"||N({view:e})}var Dn=e=>N({lobs:e==="on"});function An(e,t){let n={..._().lobHidden,[e]:t};vn(n),setTimeout(()=>T({lobHidden:n}),0)}async function Rn(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}var In=function(e,t,n,s){var r;t[0]=0;for(var i=1;i<t.length;i++){var o=t[i++],c=t[i]?(t[0]|=o?1:2,n[t[i++]]):t[++i];o===3?s[0]=c:o===4?s[1]=Object.assign(s[1]||{},c):o===5?(s[1]=s[1]||{})[t[++i]]=c:o===6?s[1][t[++i]]+=c+"":o?(r=e.apply(c,In(e,c,n,["",null])),s.push(r),c[0]?t[0]|=2:(t[i-2]=0,t[i]=r)):s.push(c)}return s},Pn=new Map;function Mn(e){var t=Pn.get(this);return t||(t=new Map,Pn.set(this,t)),(t=In(this,t.get(e)||(t.set(e,t=(function(n){for(var s,r,i=1,o="",c="",u=[0],l=function(d){i===1&&(d||(o=o.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,"")))?u.push(0,d,o):i===3&&(d||o)?(u.push(3,d,o),i=2):i===2&&o==="..."&&d?u.push(4,d,0):i===2&&o&&!d?u.push(5,0,!0,o):i>=5&&((o||!d&&i===5)&&(u.push(i,0,o,r),i=6),d&&(u.push(i,d,0,r),i=6)),o=""},f=0;f<n.length;f++){f&&(i===1&&l(),l(f));for(var h=0;h<n[f].length;h++)s=n[f][h],i===1?s==="<"?(l(),u=[u],i=3):o+=s:i===4?o==="--"&&s===">"?(i=1,o=""):o=s+o[0]:c?s===c?c="":o+=s:s===\'"\'||s==="\'"?c=s:s===">"?(l(),i=1):i&&(s==="="?(i=5,r=o,o=""):s==="/"&&(i<5||n[f][h+1]===">")?(l(),i===3&&(u=u[0]),i=u,(u=u[0]).push(2,0,i),i=0):s===" "||s===" "||s===`\n`||s==="\\r"?(l(),i=2):o+=s),i===3&&o==="!--"&&(i=4,u=u[0])}return l(),u})(e)),t),arguments,[])).length>1?t:t[0]}var En=e=>Array.isArray(e)?e.map(En):e===""?null:e,Zs=(e,t,...n)=>Q(e,t,...n.map(En)),a=Mn.bind(Zs);var Ie,k,mt,Ln,ht=0,Fn=[],y=b,Nn=y.__b,Hn=y.__r,Un=y.diffed,jn=y.__c,Bn=y.unmount,On=y.__;function Wn(e,t){y.__h&&y.__h(k,e,ht||t),ht=0;var n=k.__H||(k.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function ne(e){return ht=1,Ys(Kn,e)}function Ys(e,t,n){var s=Wn(Ie++,2);if(s.t=e,!s.__c&&(s.__=[n?n(t):Kn(void 0,t),function(c){var u=s.__N?s.__N[0]:s.__[0],l=s.t(u,c);u!==l&&(s.__N=[l,s.__[1]],s.__c.setState({}))}],s.__c=k,!k.__f)){var r=function(c,u,l){if(!s.__c.__H)return!0;var f=!1,h=s.__c.props!==c;if(s.__c.__H.__.some(function(m){if(m.__N){f=!0;var p=m.__[0];m.__=m.__N,m.__N=void 0,p!==m.__[0]&&(h=!0)}}),i){var d=i.call(this,c,u,l);return f?d||h:d}return!f||h};k.__f=!0;var i=k.shouldComponentUpdate,o=k.componentWillUpdate;k.componentWillUpdate=function(c,u,l){if(this.__e){var f=i;i=void 0,r(c,u,l),i=f}o&&o.call(this,c,u,l)},k.shouldComponentUpdate=r}return s.__N||s.__}function Vn(e,t){var n=Wn(Ie++,7);return nr(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function er(){for(var e;e=Fn.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(Pe),t.__h.some(gt),t.__h=[]}catch(n){t.__h=[],y.__e(n,e.__v)}}}y.__b=function(e){k=null,Nn&&Nn(e)},y.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),On&&On(e,t)},y.__r=function(e){Hn&&Hn(e),Ie=0;var t=(k=e.__c).__H;t&&(mt===k?(t.__h=[],k.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(Pe),t.__h.some(gt),t.__h=[],Ie=0)),mt=k},y.diffed=function(e){Un&&Un(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Fn.push(t)!==1&&Ln===y.requestAnimationFrame||((Ln=y.requestAnimationFrame)||tr)(er)),t.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),mt=k=null},y.__c=function(e,t){t.some(function(n){try{n.__h.some(Pe),n.__h=n.__h.filter(function(s){return!s.__||gt(s)})}catch(s){t.some(function(r){r.__h&&(r.__h=[])}),t=[],y.__e(s,n.__v)}}),jn&&jn(e,t)},y.unmount=function(e){Bn&&Bn(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(s){try{Pe(s)}catch(r){t=r}}),n.__H=void 0,t&&y.__e(t,n.__v))};var qn=typeof requestAnimationFrame=="function";function tr(e){var t,n=function(){clearTimeout(s),qn&&cancelAnimationFrame(t),setTimeout(e)},s=setTimeout(n,35);qn&&(t=requestAnimationFrame(n))}function Pe(e){var t=k,n=e.__c;typeof n=="function"&&(e.__c=void 0,n()),k=t}function gt(e){var t=k;e.__c=e.__(),k=t}function nr(e,t){return!e||e.length!==t.length||t.some(function(n,s){return n!==e[s]})}function Kn(e,t){return typeof t=="function"?t(e):t}var K=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=>a`<span data-age=${e??""}>${K(e)}</span>`,Ee=e=>e.activity&&a`<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>`,sr=e=>e&&/^https?:\\/\\//i.test(e)?e:void 0,Le=e=>{let t=e.waiting;if(!t)return;let n=sr(t.link),s=n;try{n&&(s=new URL(n).host+new URL(n).pathname.replace(/\\/$/,""))}catch{s=n}return a`<div class="waiting">${e.verb}: waiting on ${t.on} \xB7 ${v(t.since)}${n&&[" \\xB7 ",a`<a href=${n} target="_blank" rel="noopener noreferrer" onClick=${D}>${s}</a>`]}</div>`},rr=12,zn=e=>e!==void 0&&e.length>rr,H=e=>zn(e)?e:void 0,U=e=>zn(e)?" long":"",w=(e,t)=>()=>M(e,t),D=e=>e.stopPropagation(),or=e=>e.sessionId?(e.harness==="codex"?"codex resume ":"claude --resume ")+e.sessionId:void 0;function z(e){if(e.requested)return a`<span class="dim">Requested \u2014 no window yet</span>`;if(e.starting)return a`<span class="dim">${e.starting.failedAt?"Did not start":"Starting \\u2014 no window yet"}</span>`;if(!e.live){let s=or(e);return s?a`<span class="dim">Resume: <code onClick=${D}>${s}</code></span>`:a`<span class="dim">Resume command unavailable</span>`}let t=_();return!t.snapshot?.focusSupported&&!e.link?a`<span class="dim">Window focus is not supported here</span>`:a`<span class="winaction"><button class="btn open" title="open this trap\'s window" onClick=${s=>{D(s),Tn(e.trapId)}}>\u2197 open</button>${e.link&&[" ",a`<a href=${e.link} onClick=${D}>Session link</a>`]}${t.focusResults[e.trapId]&&[" ",a`<span class="dim">${t.focusResults[e.trapId]}</span>`]}</span>`}function R(e,t,n){return t.length?a`<div class="wrap"><table><tbody><tr>${e.map(s=>a`<th>${s}</th>`)}</tr>${t}</tbody></table></div>`:a`<div class="empty">${n}</div>`}function ir({text:e}){let[t,n]=ne(null),s=r=>async()=>{await Rn(e)&&(n(r),setTimeout(()=>n(null),1e3))};return a`<div class="cmd"><code class=${t==="code"?"copied":void 0} title="click to copy" onClick=${s("code")}>${e}</code><button title="copy" onClick=${s("button")}>${t==="button"?"\\u2713":"\\u29C9"}</button></div>`}var S=(e,t)=>a`<${ir} key=${t} text=${e} />`,ue=(e,t,n="thumb")=>a`<button\n type="button"\n class=${n}\n title=${"view "+t}\n onClick=${s=>{D(s),xn(e,t)}}\n >\n <img src=${e} alt=${t} loading="lazy" />\n </button>`,se=(e,t)=>e.map(n=>[a`<div class="sub">${n.name} \xB7 ${n.type} \xB7 ${n.bytes} bytes</div>`,t&&rn(n.name)&&ue(t(n.name),n.name),S(n.path)]),Jn=/\\bwt:([a-z0-9][a-z0-9-]*)/g,vt=e=>_().snapshot?.trapNames?.[e],j=e=>e.replace(Jn,(t,n,s)=>{let r=vt(n);return r&&!Xn(e,s,t.length,r)?r:t}),Xn=(e,t,n,s)=>e.slice(Math.max(0,t-s.length-2),t)===`${s} (`&&e[t+n]===")";function Ne(e){let t="wt:"+e,n=vt(e)??t;return _().snapshot?.traps.some(r=>r.trapId===e)?a`<a class="trapname" href="#traps" title=${t} onClick=${r=>{r.preventDefault(),D(r),M("trap",e)}}>${n}</a>`:a`<span class="trapname" title=${t}>${n}</span>`}var Me=e=>{let t=/^wt:([a-z0-9][a-z0-9-]*)$/.exec(e);return t?Ne(t[1]):e};function B(e,t=1/0){let n=[],s=0;for(let c of e.matchAll(Jn)){c.index>s&&n.push({text:e.slice(s,c.index)});let u=vt(c[1]);n.push(u&&Xn(e,c.index,c[0].length,u)?{text:c[0]}:{text:u??c[0],trapId:c[1]}),s=c.index+c[0].length}s<e.length&&n.push({text:e.slice(s)});let r=n.reduce((c,u)=>c+u.text.length,0),i=r>t?t-1:1/0,o=[];for(let c of n){if(i<=0)break;c.text.length<=i?o.push(c.trapId?Ne(c.trapId):c.text):o.push(c.text.slice(0,i)),i-=c.text.length}return r>t&&o.push("\\u2026"),o}var _t=e=>e.log.flatMap((t,n)=>[n?`\n`:"",t.at+" "+t.verb,...t.note?[" ",...B(t.note)]:[]]);function Qn(e){let t=[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`);return a`${e.waiting&&[a`<div class="sec">waiting</div>`,Le(e)]}${e.activity&&[a`<div class="sec">activity</div>`,Ee(e)]}${t&&[a`<div class="sec">progress</div>`,a`<pre>${t}</pre>`]}<div class="sec">brief</div><pre>${e.brief}</pre>${e.attachments.length>0&&[a`<div class="sec">attachments (${e.attachments.length})</div>`,se(e.attachments,n=>it(e.lane,e.id,n))]}${e.messageAttachments.length>0&&[a`<div class="sec">message attachments (${e.messageAttachments.length})</div>`,se(e.messageAttachments,n=>it(e.lane,e.id,n))]}${e.followUp&&[a`<div class="sec">forks</div>`,a`<pre>${e.followUp}</pre>`]}<div class="sec">log</div><div class="loglines">${e.log.length?_t(e):"no entries yet"}</div>${e.inbox.length>0&&[a`<div class="sec">inbox</div>`,a`<div class="loglines">${e.inbox.join(`\n---\n`)}</div>`]}${e.awaitingReply&&[a`<div class="sec">awaiting reply</div>`,a`<div>${e.awaitingReply.line} \xB7 from ${e.awaitingReply.from} \xB7 ${v(e.awaitingReply.sentAt)} ago</div>`]}${e.evidence&&[a`<div class="sec">evidence</div>`,a`<div class="loglines">${JSON.stringify(e.evidence)}</div>`]}`}function fe(e){return e.for?[Me(e.for),e.evidence&&e.evidence.deliveredTo?[" ",a`<span class="ok">\u2713delivered</span>`]:[" ",a`<span class="warn">waiting</span>`]]:e.claimedBy?Me(e.claimedBy):""}function re(e){let t=e.evidence&&(e.evidence.prUrl||e.evidence.pr&&e.evidence.pr.url);if(!t)return"";let n=e.prBadge;return[a`<a href=${t} target="_blank" rel="noopener" onClick=${D}>PR</a>`,n&&[" ",a`<span class=${"badge "+L(n)} title=${"observed "+n.observedAt}>${n.text}</span>`],e.prGate&&[" ",a`<span class="badge dim" title="merge gate (pick)">${e.prGate}</span>`]]}var ar={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready",landed:"landed",watch:"watch"},$t={"pr:review":"bad","pr:checks":"bad","pr:conflict":"pr-conflicts","pr:ready":"ok","pr:draft":"dim",watch:"warn"},Zn=e=>ar[e]||"";var He=e=>a`<a href=${e.url} target="_blank" rel="noopener" onClick=${D}>#${e.number}</a>`,Ue=e=>a`<span class="prname" title=${e.title||void 0}><b>#${e.number}</b>${e.title&&[" ",e.title]}</span>`;function oe(e,t,n){return e.flatMap((s,r)=>{let i=t.get(s)||void 0,o=s===n?a`<b title=${i}>#${s}</b>`:a`<span title=${i}>#${s}</span>`;return r?[" \\u2192 ",o]:[o]})}function me(e){let t=e.checks;return t.passed+"/"+t.total+" passed"+(t.failed?" \\xB7 "+t.failed+" failed":"")+(t.pending?" \\xB7 "+t.pending+" pending":"")}function je(e){let t=e.review||{};return(e.reviewDecision||"")+(t.unresolvedThreads?" \\xB7 "+t.unresolvedThreads+" unresolved":"")+(t.changesRequested?" \\xB7 changes requested":"")}function he(e){return[e.mergeStateStatus,e.nextMergeable?[" \\xB7 ",a`<span class="ok">next mergeable</span>`]:e.blockedBy?" \\xB7 blocked by #"+e.blockedBy:""]}function bt(e){let t=fn(e);return e?[t.text," \\xB7 ",t.at?[v(t.at)," ago"]:"never checked"]:a`<span class="dim">${t.text}</span>`}function ge(e){if(e.requested)return{stale:!1,listen:[a`<span class="dot"></span>`,a`<span class="dim">requested</span>`],hb:a`<span class="dim">\u2014</span>`};if(e.starting)return{stale:!1,listen:e.starting.failedAt?[a`<span class="dot bad"></span>`,a`<span class="bad">start failed</span>`]:[a`<span class="dot warn"></span>`,"starting"],hb:a`<span class="dim">\u2014</span>`};if(!e.live)return{stale:!1,listen:[a`<span class="dot"></span>`,a`<span class="dim">signed off</span>`],hb:a`<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?[a`<span class="dot ok"></span>`,"listening"]:[a`<span class="dot warn"></span>`,"not listening"],hb:a`<span class=${t?"bad":"ok"}>${t&&"stale "}${v(e.heartbeatAt)} ago</span>`}}function kt(e){if(e.requested)return{kind:"requested",helmOn:!!_().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 lr(e){let t=kt(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 Yn=e=>e.waiting?`waiting on ${e.waiting.on}`:e.note||"waiting",es=e=>e.brief.split(/\\r?\\n/,1)[0]?.trim().slice(0,40)||"(no title)";function ve(e){let t=kt(e),n=a`<span class=${"dot trapdot "+lr(e)}></span>`;if(t.kind==="requested")return[n,a`<span class="dim">${ts(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,a`<span class="bad">start failed</span>`," \\xB7 ",t.reason];if(t.kind==="signed off")return[n,a`<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 ",Yn(s)]:[n,"working \\xB7 ",a`<a href="#dispatches" onClick=${i=>{i.preventDefault(),D(i),M("dispatch",`${s.lane}:${s.id}`)}}>${s.id.slice(0,8)}</a>`," \\xB7 ",es(s),s.activity&&[" \\xB7 ",s.activity.summary," ",v(s.activity.at)," ago"]]}var ts=(e,t)=>`requested \\xB7 ${e.repo??""} \\xB7 ${e.harness??""} \\xB7 ${t?"waiting for the helm":"waiting for a helm"}`;function J(e){let t=e.starting?.commands;return t?.length?a`<div class="startcmds" onClick=${D}><div class="dim">start it: run one in a terminal</div>${t.map(n=>S(n.command,n.harness))}</div>`:null}function Be(){let t=_().snapshot?.repoKeys??[],[n,s]=ne(!1),[r,i]=ne(""),[o,c]=ne("claude"),[u,l]=ne(null),f=r||t[0]||"",h=async d=>{d.preventDefault();let m=await Sn(f,o);l(m??null),m||s(!1)};return n?a`<form class="newtrap" onClick=${D} onSubmit=${h}>\n <label>repo <select name="repo" value=${f} onChange=${d=>i(d.target.value)}>${t.map(d=>a`<option value=${d}>${d}</option>`)}</select></label>\n <label>harness <select name="harness" value=${o} onChange=${d=>c(d.target.value)}><option value="claude">claude</option><option value="codex">codex</option></select></label>\n <button class="btn" type="submit" disabled=${!f}>Request</button>\n <button class="btn" type="button" onClick=${()=>s(!1)}>Cancel</button>\n ${u&&a`<span class="bad">${u}</span>`}\n </form>`:a`<span class="newtrap"><button class="btn" onClick=${d=>(D(d),s(!0),l(null))}>+ New trap</button></span>`}function Oe(e){let t=kt(e);if(t.kind==="requested")return ts(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 ${Yn(t.current)}`;let n=t.current;return[`working \\xB7 ${n.id.slice(0,8)} \\xB7 ${es(n)}`,n.activity&&`${n.activity.summary} ${K(n.activity.at)} ago`].filter(Boolean).join(" \\xB7 ")}function yt(e){let t=e.messages.filter(n=>n.state==="pending").length;return e.messages.length?["\\u2709 "+e.messages.length,t>0&&[" ",a`<span class="warn">(${t} pending)</span>`]]:null}var cr=e=>()=>{window.open(C(e.key),"_blank","noopener")};function wt(e){let t=de(e);return{nodes:[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked?" \\xB7 acked":""],text:[t,`${K(e.filedAt)} ago`,e.acked?"acked":""].filter(Boolean).join(" \\xB7 ")}}function dr(e){let t=wt(e);return a`<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 pr(e){return a`<tr key=${e.key} class=${"rowhead"+(e.acked?" acked":"")} onClick=${cr(e)}><td class="grow"><a href=${C(e.key)} target="_blank" rel="noopener" onClick=${t=>t.stopPropagation()}>${e.title}</a></td><td>${de(e)}</td><td>${v(e.filedAt)}</td><td>${e.acked?"acked":""}</td></tr>`}function ns({inp:e}){return e.view==="cards"?e.list.length?a`<div class="cards">${e.list.map(dr)}</div>`:a`<div class="empty">no reports match</div>`:R(["title","from","filed","acked"],e.list.map(pr),"no reports match")}function os(e){let t=e.trim();return/^(https?:\\/\\/|mailto:|#)/i.test(t)?t:void 0}function is(e){let t=e.trim();return/^[^/\\\\:?#]+$/.test(t)&&t!=="."&&t!==".."?t:void 0}function ss(e,t,n,s){let r=0;for(let i=t;i<e.length;i++){if(e[i]==="\\\\"){i++;continue}if(e[i]===n)r++;else if(e[i]===s){if(r===0)return i;r--}}return-1}function rs(e,t){let n=ss(e,t+1,"[","]");if(n<0||e[n+1]!=="(")return;let s=ss(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 i=e[r];if(i==="\\\\"&&r+1<e.length&&/[\\\\`*_{}[\\]()#+\\-.!|<>~]/.test(e[r+1])){n+=e[r+1],r+=2;continue}if(i==="`"){let o=/^`+/.exec(e.slice(r))[0],c=e.indexOf(o,r+o.length);if(c>0){s(),t.push({t:"code",v:e.slice(r+o.length,c).replace(/^ (.*) $/,"$1")}),r=c+o.length;continue}}if(i==="!"&&e[r+1]==="["){let o=rs(e,r+1);if(o){s(),t.push({t:"img",alt:o.text,src:o.target}),r=o.end;continue}}if(i==="["){let o=rs(e,r);if(o){s(),t.push({t:"a",href:o.target,c:q(o.text)}),r=o.end;continue}}if((i==="*"||i==="_")&&e[r+1]===i){let o=e.indexOf(i+i,r+2);if(o>r+2){s(),t.push({t:"b",c:q(e.slice(r+2,o))}),r=o+2;continue}}if(i==="*"||i==="_"&&(r===0||!/\\w/.test(e[r-1]))){let o=r+1;for(;(o=e.indexOf(i,o))>0&&(e[o+1]===i||i==="_"&&/\\w/.test(e[o+1]??""));)o+=2;if(o>r+1&&e[r+1]!==" "){s(),t.push({t:"i",c:q(e.slice(r+1,o))}),r=o+1;continue}}if(i===`\n`){/ {2,}$/.test(n)||n.endsWith("\\\\")?(n=n.replace(/( {2,}|\\\\)$/,""),s(),t.push({t:"br"})):n+=" ",r++;continue}n+=i,r++}return s(),t}var as=/^ {0,3}(`{3,}|~{3,})\\s*([^`\\s]*)/,ls=/^ {0,3}(#{1,6})\\s+(.*?)\\s*#*\\s*$/,cs=/^ {0,3}([-*_])(\\s*\\1){2,}\\s*$/,Tt=/^( {0,3})([-*+])\\s+(.*)$/,St=/^( {0,3})(\\d{1,9})[.)]\\s+(.*)$/,qe=/^ {0,3}>\\s?(.*)$/,ur=/^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;function Gt(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 xt=e=>as.test(e)||ls.test(e)||cs.test(e)||Tt.test(e)||St.test(e)||qe.test(e);function Fe(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 i=as.exec(r);if(i){let f=i[1],h=[];for(s++;s<t.length&&!new RegExp(`^ {0,3}${f[0]}{${f.length},}\\\\s*$`).test(t[s]);)h.push(t[s++]);s++,n.push({t:"code",lang:i[2]??"",v:h.join(`\n`)});continue}let o=ls.exec(r);if(o){n.push({t:"h",level:o[1].length,c:q(o[2])}),s++;continue}if(cs.test(r)){n.push({t:"hr"}),s++;continue}if(qe.test(r)){let f=[];for(;s<t.length&&t[s].trim()&&(qe.test(t[s])||!xt(t[s]));)f.push(qe.exec(t[s])?.[1]??t[s]),s++;n.push({t:"quote",c:Fe(f.join(`\n`))});continue}let c=Tt.exec(r),u=St.exec(r);if(c||u){let f=!c,h=f?St:Tt,d=[];for(;s<t.length;){let m=t[s],p=h.exec(m);if(p&&p[1].length<=3){d.push([p[3]]),s++;continue}if(!m.trim()){if(s+1<t.length&&/^ {2,}\\S/.test(t[s+1])){d.at(-1).push(""),s++;continue}break}if(/^ {2,}\\S/.test(m)){d.at(-1).push(m.replace(/^ {2,4}/,"")),s++;continue}if(xt(m))break;d.at(-1).push(m.trim()),s++}n.push({t:"list",ordered:f,start:f?Number(u[2]):1,items:d.map(m=>Fe(m.join(`\n`)))});continue}if(r.includes("|")&&s+1<t.length&&ur.test(t[s+1])&&t[s+1].includes("-")){let f=Gt(r),h=Gt(t[s+1]).map(m=>m.startsWith(":")&&m.endsWith(":")?"center":m.endsWith(":")?"right":m.startsWith(":")?"left":"");s+=2;let d=[];for(;s<t.length&&t[s].trim()&&t[s].includes("|");){let m=Gt(t[s++]);d.push(f.map((p,g)=>q(m[g]??"")))}n.push({t:"table",align:f.map((m,p)=>h[p]??""),head:f.map(q),rows:d});continue}let l=[];for(;s<t.length&&t[s].trim()&&!xt(t[s])&&!(l.length&&/^ {0,3}(=+|-+)\\s*$/.test(t[s]));)l.push(t[s++].replace(/^ +/,""));if(l.length===0){n.push({t:"p",c:q(r.trim())}),s++;continue}n.push({t:"p",c:q(l.join(`\n`))})}return n}function F(e,t){return t.map(n=>{switch(n.t){case"text":return n.v;case"code":return a`<code>${n.v}</code>`;case"b":return a`<strong>${F(e,n.c)}</strong>`;case"i":return a`<em>${F(e,n.c)}</em>`;case"br":return a`<br />`;case"a":{let s=os(n.href);return s?a`<a href=${s} target="_blank" rel="noopener noreferrer">${F(e,n.c)}</a>`:F(e,n.c)}case"img":{let s=is(n.src);return s?ue(e(s),n.alt||s,"mdimg"):a`<span class="dim">[image not shown: ${n.alt||n.src}]</span>`}}})}function We(e,t){return t.map(n=>{switch(n.t){case"h":{let s=F(e,n.c);return n.level===1?a`<h1>${s}</h1>`:n.level===2?a`<h2>${s}</h2>`:n.level===3?a`<h3>${s}</h3>`:a`<h4>${s}</h4>`}case"p":return a`<p>${F(e,n.c)}</p>`;case"code":return a`<pre class="mdcode"><code>${n.v}</code></pre>`;case"hr":return a`<hr />`;case"quote":return a`<blockquote>${We(e,n.c)}</blockquote>`;case"list":{let s=n.items.map(r=>a`<li>${We(e,r)}</li>`);return n.ordered?a`<ol start=${n.start}>${s}</ol>`:a`<ul>${s}</ul>`}case"table":return a`<div class="mdtable"><table><thead><tr>${n.head.map((s,r)=>a`<th style=${n.align[r]?"text-align:"+n.align[r]:void 0}>${F(e,s)}</th>`)}</tr></thead><tbody>${n.rows.map(s=>a`<tr>${s.map((r,i)=>a`<td style=${n.align[i]?"text-align:"+n.align[i]:void 0}>${F(e,r)}</td>`)}</tr>`)}</tbody></table></div>`}})}var _e=new Map;function ds(e){let t=_e.get(e);return t||(t=Fe(e),_e.set(e,t),_e.size>8&&_e.delete(_e.keys().next().value)),t}function fr({r:e,text:t}){let n=t?.text!==void 0?We(s=>ct(e.key,s),ds(t.text)):t?.error?a`<div class="bad">${t.error}</div>`:a`<div class="dim">loading\u2026</div>`;return a`<div class="mdpage" data-report=${e.key}>${n}</div>`}function ps({text:e,fileUrl:t}){return a`<div class="mdpage">${We(t,ds(e))}</div>`}function Ct(e){let t=de(e);return[t&&t+" \\xB7 ",v(e.filedAt)," ago",e.acked&&[" \\xB7 ",a`<span class="ok">acked</span>`]]}function us({r:e,text:t,heading:n}){return[n&&a`<div class="sec">report \xB7 ${e.title}</div>`,a`<div class="sub">${Ct(e)}</div>`,a`<${fr} r=${e} text=${t} />`,e.attachments.length>0&&[a`<div class="sec">report attachments (${e.attachments.length})</div>`,se(e.attachments,s=>ct(e.key,s))],!e.acked&&[a`<div class="sec">ack</div>`,S("lobstah attention ack "+e.key)]]}var mr=/\\.(png|jpe?g|gif|webp)$/i,hr=e=>{e.style.height="auto",e.style.height=e.scrollHeight+"px"};function gr(e,t){return t.length?a`<div class="dfiles">${t.map(n=>mr.test(n.name)?a`<span key=${n.name}>${ue(at(e,n.name),n.name,"dimg")}</span>`:a`<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 vr(e,t,n){let s=e.key,r=e.kind==="decision"?e.options:[],i=t?.text??"",o=t?.files??[],c=!!t?.sending;return[r.length>0&&a`<div class="doptions">${r.map(u=>a`<button key=${u} type="button" class=${"btn dopt"+(t?.option===u?" on":"")} aria-pressed=${t?.option===u?"true":"false"} disabled=${c} onClick=${()=>bn(s,u)}>${u}</button>`)}</div>`,a`<textarea\n class="danswer"\n rows="2"\n placeholder=${r.length?"Add to your answer, or answer in your own words":"Your answer"}\n value=${i}\n disabled=${c}\n onInput=${u=>{let l=u.currentTarget;hr(l),A(s,{text:l.value,error:void 0})}}\n onPaste=${u=>{kn(s,u)}}\n ></textarea>`,a`<div class="dfoot">\n <label class="btn dattach" title="attach images or files">attach<input type="file" multiple accept=${n} disabled=${c} onChange=${u=>{let l=u.currentTarget;ft(s,l.files).then(()=>{l.value=""})}} /></label>\n ${o.map((u,l)=>a`<span key=${u.name+l} class="dchip">${u.name}<button type="button" class="dx" title="remove" disabled=${c} onClick=${()=>yn(s,l)}>\xD7</button></span>`)}\n ${t?.error&&a`<span class="bad derr">${t.error}</span>`}\n <button type="button" class="btn dsend" disabled=${c} onClick=${()=>{wn(s)}}>${c?"Sending\\u2026":"Send"}</button>\n </div>`]}function _r(e,t,n,s){let r=e.dispatch,i=e.lane??"work",c=[r&&a`<a class="dlink" href="#" onClick=${l=>{l.preventDefault(),w("dispatch",i+":"+r)()}}>${r.slice(0,8)}</a>`,e.repo,[v(e.at)," ago"]].filter(Boolean).flatMap((l,f)=>f?[" \\xB7 ",l]:[l]),u="dcard"+(e.kind==="question"?" plain":"")+(t?.sent?" answered":"")+(n?" focus":"");return a`<div key=${e.key} class=${u} data-decision=${e.key}>\n <div class="dtop">\n ${e.kind==="question"&&a`<span class=${"badge "+(e.verb==="blocked"?"bad":"warn")}>${e.verb}</span>`}\n <b class="dtitle">${e.kind==="decision"?e.title:B(e.note)}</b>\n <span class="dmeta dim">${c}</span>\n </div>\n ${e.kind==="decision"&&e.detail.trim()&&a`<${ps} text=${e.detail} fileUrl=${l=>at(e.key,l)} />`}\n ${e.kind==="decision"&&gr(e.key,e.attachments)}\n ${t?.sent?a`<div class="danswered ok">answered \xB7 ${t.sent}</div>`:vr(e,t,s)}\n </div>`}function fs({cards:e,drafts:t,focus:n,extensions:s}){let r=s.join(","),i=e.length?a`<div class="dcards">${e.map(o=>_r(o,t[o.key],o.key===n,r))}</div>`:a`<div class="empty">none</div>`;return a`<section class="decisions"><h2>decisions</h2>${i}</section>`}function yr(e,t){let n=e.badge&&a`<span class=${"badge "+(e.badge.tone||"dim")+U(e.badge.text)} title=${H(e.badge.text)}>${e.badge.text}</span>`;if(e.href){let s=(t==="cards"?"card":"deckline click")+(e.acked?" acked":"");return t==="cards"?a`<a key=${e.key} class=${s} href=${e.href} target="_blank" rel="noopener"><div class="top"><b>${e.title}</b>${n}</div>${e.meta&&a`<div class="meta" title=${e.metaText}>${e.meta}</div>`}</a>`:a`<a key=${e.key} class=${s} href=${e.href} target="_blank" rel="noopener">${n&&[n," "]}<b>${e.title}</b>${e.meta&&[" ",a`<span class="dim">\xB7 ${e.meta}</span>`]}</a>`}return t==="cards"?a`<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>${n}</div>${e.meta&&a`<div class="meta" title=${e.metaText}>${e.meta}</div>`}${e.extra}${e.action&&a`<div class="foot"><span class="footact">${e.action}</span></div>`}</div>`:a`<div key=${e.key} class=${"deckline"+(e.open?" click":"")+(e.acked?" acked":"")} onClick=${e.open}>${n&&[n," "]}<b>${e.title}</b>${e.meta&&[" ",a`<span class="dim">\xB7 ${e.meta}</span>`]}${e.action&&[" ",a`<span class="dim">\xB7 </span>`,e.action]}${e.extra}</div>`}var ms=(e,t)=>e>0&&a`<a class="deckmore" href=${"#"+t}>+${e} more \u2192</a>`;function Ve(e,t,n,s,r,i){let o=t.slice(0,s),c=o.map(l=>yr(l,r)),u=o.length?r==="cards"?a`<div class="cards">${c}</div>`:c:a`<div class="empty">none</div>`;return a`<section><h2><a href=${"#"+n}>${e} \u2192</a></h2>${i&&a`<div class="tabhead">${i}</div>`}${u}${ms(t.length-o.length,n)}</section>`}function wr(e,t,n,s){let r=t.find(l=>l.number===e.nextNumber)||t[0],i=oe(e.numbers,new Map(t.map(l=>[l.number,l.title]))),o=r?"next #"+r.number:"nothing mergeable";if(s==="cards"){let l=f=>{let h=n.get(f.key)||[],d=h.length>0&&h.every(g=>g.acked),m=h.length?h.map(g=>a`<span class=${"badge "+($t[g.kind]||"dim")}>${Zn(g.kind)}</span>`):a`<span class=${"badge "+L(f.badge)+U(f.badge.text)} title=${H(f.badge.text)}>${f.badge.text}</span>`,p=`${f.repo} \\xB7 ${f.badge.text}${d?" \\xB7 acked":""}`;return a`<div key=${f.key} class=${"card"+(d?" acked":"")} onClick=${w("pr",f.key)}><div class="top">${Ue(f)}${m}</div><div class="meta" title=${p}>${p}</div></div>`};return a`<div key=${e.id} class="deckstack"><div class="dim">${i} \xB7 ${o}</div><div class="cards">${t.map(l)}</div></div>`}let c=t.flatMap(l=>(n.get(l.key)||[]).map(f=>a`<span class=${"badge "+($t[f.kind]||L(l.badge))+(f.acked?" acked":"")}>#${l.number} ${l.badge.text}</span>`)),u=c.flatMap((l,f)=>f?[" ",l]:[l]);return a`<div key=${e.id} class=${"deckline"+(r?" click":"")} onClick=${r&&w("pr",r.key)}><b>${i}</b> <span class="dim">\xB7 ${o}</span>${c.length>0&&[" \\xB7 ",u]}</div>`}function Gr(e,t){let n=e.stacks.slice(0,3),s=new Map;for(let i of e.prAttention){let o=s.get(i.key)||[];o.push(i),s.set(i.key,o)}let r=n.length?n.map(i=>wr(i,e.prs.filter(o=>o.stackId===i.id).sort((o,c)=>o.position-c.position),s,t)):a`<div class="empty">none</div>`;return a`<section><h2><a href="#prs">PRs \u2192</a></h2>${r}${ms(e.stacks.length-n.length,"prs")}</section>`}function hs({inp:e,drafts:t,focus:n,extensions:s}){let r=e.view,i=e.inflight.map(l=>({key:l.lane+":"+l.id,title:[l.id.slice(0,8)," ",l.repo||""],badge:{text:l.verb,tone:l.verb==="needs-decision"||l.verb==="blocked"?"bad":"dim"},meta:[B(l.note||"",90),l.verbAt&&[" \\xB7 ",v(l.verbAt)," ago"],(l.for||l.claimedBy)&&[" \\xB7 ",Me(l.for||l.claimedBy)]],metaText:[j(l.note||""),l.verbAt&&`${K(l.verbAt)} ago`,j(l.for||l.claimedBy||"")].filter(Boolean).join(" \\xB7 "),open:w("dispatch",l.lane+":"+l.id)})),o=e.landed.map(l=>({key:l.key,title:[l.id.slice(0,8)," ",l.repo||"",l.unreported&&[" ",a`<span class="badge warn unreported">unreported</span>`]],badge:{text:l.verb,tone:l.verb==="failed"?"bad":"ok"},meta:[B(l.note||"",90)," \\xB7 ",v(l.at)," ago"],metaText:`${j(l.note||"")} \\xB7 ${K(l.at)} ago`,open:w("dispatch",l.lane+":"+l.id)})),c=e.reports.map(l=>{let f=wt(l);return{key:l.key,title:l.title,meta:f.nodes,metaText:f.text,href:C(l.key),acked:!!l.acked}}),u=e.traps.map(({x:l})=>({key:l.trapId,title:"\\u{1FAA4} "+(l.label??`wt:${l.trapId}`),badge:l.requested?{text:"requested",tone:"dim"}:l.starting?{text:l.starting.failedAt?"start failed":"starting",tone:l.starting.failedAt?"bad":"warn"}:{text:l.live?l.harness||"live":"signed off",tone:l.live?"ok":"dim"},meta:[l.repo||""," \\xB7 ",ve(l)],metaText:`${l.repo||""} \\xB7 ${Oe(l)}`,action:z(l),extra:J(l),open:w("trap",l.trapId)}));return a`<div class="deckgrid"><${fs} cards=${e.decisions} drafts=${t} focus=${n} extensions=${s} />${Ve("in flight",i,"dispatches",4,r)}${Ve("Landed \\xB7 24h",o,"dispatches",8,r)}${Ve("reports",c,"reports",8,r)}${Ve("traps",u,"traps",8,r,a`<${Be} />`)}${Gr(e,r)}</div>`}function xr(e,t){if(!t)return e;let n=new Map(e.map(i=>[i.id,i])),s=i=>{let o=i,c=new Set;for(;o.followUp&&n.has(o.followUp)&&!c.has(o.id);)c.add(o.id),o=n.get(o.followUp);return o.id},r=new Map;for(let i of e){let o=s(i),c=r.get(o)||[];c.push(i),r.set(o,c)}return[...r.values()].sort((i,o)=>o[0].sort-i[0].sort).flatMap(i=>i.sort((o,c)=>o.id===s(o)?-1:c.id===s(c)?1:o.sort-c.sort))}function Tr(e,t){let n=e.lane+":"+e.id;return a`<tr key=${n} class="rowhead" onClick=${w("dispatch",n)}><td>${t&&e.followUp&&a`<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">${B(e.note??"",90)}${Le(e)}${Ee(e)}</td><td>${v(e.verbAt)}</td><td>${fe(e)}</td><td>${re(e)}</td></tr>`}function Sr(e){let t=e.lane+":"+e.id;return a`<div key=${t} class="card" onClick=${w("dispatch",t)}><div class="top"><b>${e.id.slice(0,8)}</b><span class=${"badge v-"+e.verb+U(e.verb)} title=${H(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&&a`<div class="note" title=${j(e.note)}>${B(e.note)}</div>`}${Le(e)}${Ee(e)}<div class="foot">${fe(e)} ${re(e)}</div></div>`}function gs({inp:e}){let t=e.list;return e.view==="cards"?t.length?a`<div class="cards">${t.map(Sr)}</div>`:a`<div class="empty">no dispatches match</div>`:R(["id","lane / bucket","repo","verb","note","age","addressed","pr"],xr(t,e.chain).map(n=>Tr(n,e.chain)),"no dispatches match")}var Cr={deck:"On deck",dispatches:"Dispatches",traps:"Traps",prs:"PRs",reports:"Reports",notices:"Notices"},Dr=["working","needs-decision","blocked","paused","done","failed","unknown"];function Ar(e,t){let n=t.daemonStale,s=e.daemon?[a`<span class=${n?"bad":"ok"}>${n&&"stale "}${v(e.daemon.heartbeat)} ago</span>`," ",a`<span class="dim">v${e.daemon.version}</span>`]:a`<span class="bad">down</span>`;return[a`<span class="chip">daemon ${s}</span>`,e.slots&&a`<span class="chip">active headless: ${e.slots.headless} of ${e.slots.limit}; traps: ${e.slots.traps}${e.slots.parked?`; parked: ${e.slots.parked} (no slot)`:""}</span>`,t.helms.map(({x:r,stale:i})=>a`<span key=${r.grounds} class="chip click" onClick=${w("helm",r.grounds)}>\u26F5 <b>${r.man}</b> <span class="dim">helm ${r.grounds}</span> <span class=${i?"warn":"ok"}>${i&&"stale "}${v(r.heartbeatAt)} ago</span></span>`)]}var Dt=[];function Rr(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!==Dt.length&&(Dt=t),Dt}var At=[];function Pr(e){let t=[...new Set(e.notices.map(n=>n.kind))].sort();return t.length!==At.length&&(At=t),At}var $e=e=>e.currentTarget.value;function Ir(e,t,n){let s=o=>t===o?"":"display:none",r=e?Rr(e):[],i=e?Pr(e):[];return a`<div class="controls">\n <select id="f-lane" style=${e&&s("dispatches")} value=${n.lane} onChange=${o=>N({lane:$e(o)})}>\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=${o=>N({repo:$e(o)})}>\n <option value="">all repos</option>\n ${r.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <select id="f-verb" style=${e&&s("dispatches")} value=${n.verb} onChange=${o=>N({verb:$e(o)})}>\n <option value="">all verbs</option>\n ${Dr.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <label id="chain-control" style=${e&&s("dispatches")}><input id="f-chain" type="checkbox" checked=${!!n.chain} onChange=${o=>N({chain:o.currentTarget.checked})} /> group by chain</label>\n <select id="f-kind" style=${e&&s("notices")} value=${n.noticeKind} onChange=${o=>N({noticeKind:$e(o)})}>\n <option value="">all notice kinds</option>\n ${i.map(o=>a`<option key=${o}>${o}</option>`)}\n </select>\n <input id="f-q" type="search" placeholder="search id \xB7 note \xB7 brief" value=${n.q} onInput=${o=>N({q:$e(o)})} />\n </div>`}function vs({d:e,inp:t,tab:n,st:s,stale:r}){return[a`<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=${()=>M("settings","browser")}>\u2699</button></span></div>`,a`<div class="chips"><span id="chips" style="display:contents">${e&&t&&Ar(e,t.chips)}</span><span class="chip dim" id="clock">${e&&new Date(e.now).toLocaleTimeString("en-GB")}</span></div>`,a`<nav class="tabs" id="tabs" aria-label="Spyglass views">${ce.map(i=>a`<a href=${"#"+i} data-tab=${i} class=${e?i===n?"on":"":void 0}>${Cr[i]}</a>`)}</nav>`,Ir(e,n,s)]}var _s=({d:e})=>e&&["\\u{1F99E}\\u2728 lobstah v"+e.version+" \\xB7 ",a`<a href=${e.repoUrl} target="_blank">${e.repoUrl.replace("https://github.com/","")}</a>`];function $s(e,t){if(!t.lobs)return[];let n={"pr:draft":"draft","pr:review":"review","pr:checks":"checks","pr:conflict":"conflicts","pr:ready":"ready",landed:"landed",watch:"watch",report:"report"},s=t.hidden??{},r=e.filter(o=>!o.acked&&!(o.key!==void 0&&s[o.key]===o.stateHash)).map(o=>{let c=n[o.kind??""]??"",u=o.key!==void 0?{hideKey:o.key,hideHash:o.stateHash??""}:{};return o.kind==="decision"&&o.key?{key:"decision:"+o.key,text:o.note||o.verb,label:c,hash:rt(o.key),...u}:(o.kind??"question")==="question"&&o.key?{key:"question:"+o.key,text:o.note||o.verb,label:c,hash:rt(o.key),...u}:o.kind==="report"&&o.key?{key:"report:"+o.key,text:o.note||o.verb,label:c,href:C(o.key),...u}:typeof o.kind=="string"&&o.kind.startsWith("pr:")&&o.prUrl?{key:o.kind+":"+(o.key??o.prUrl),text:o.note||o.kind,href:o.prUrl,label:c,...u}:{key:(o.kind??"question")+":"+(o.key??o.lane+":"+o.id),text:o.note||o.verb,label:c,...o.kind==="watch"?{}:{open:{type:"dispatch",key:o.lane+":"+o.id}},...u}});!r.length&&t.preview&&(r=[{key:"preview",text:"attention questions crawl in here",...t.previewHelm?{open:{type:"helm",key:t.previewHelm}}:{}}]);let i=r.length>4?r.length-4:0;return r=r.slice(0,4),i&&(r[3]={...r[3],text:"\\u2026and "+i+" more \\u2014 see attention",label:""}),r}var bs=!0;function Mr(e,t,n){let s="animation-duration:"+((innerWidth+180)/(100+t*12)).toFixed(1)+"s;animation-delay:-"+t*9%14+"s",r=()=>{e.hideKey&&An(e.hideKey,e.hideHash??"")},i=[a`<div class="bub">${e.label&&[a`<span class="badge dim">${e.label}</span>`," "]}<span>${e.text.length>48?e.text.slice(0,47)+"\\u2026":e.text}</span></div>`,n===!1?a`<span class="fallback">\u{1F99E}</span>`:a`<div class="sprite"></div>`,bs&&a`<img\n class="star"\n src="/star.png"\n alt=""\n onError=${c=>{bs=!1,c.currentTarget.remove()}}\n />`],o=e.open;return e.hash?a`<a key=${e.key} class="lob" style=${s} title="open the decision" href=${e.hash} onClick=${r}>${i}</a>`:e.href?a`<a key=${e.key} class="lob" style=${s} title=${e.label==="report"?"open the report":"open the PR"} href=${e.href} target="_blank" rel="noopener" onClick=${r}>${i}</a>`:a`<div\n key=${e.key}\n class="lob"\n style=${s}\n title="click to open"\n onClick=${()=>{r(),o&&M(o.type,o.key)}}\n >\n ${i}\n </div>`}function ks({state:e}){let t=e.snapshot,n=$s(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("|")+(e.spriteOk===null?"?":e.spriteOk?"s":"e");return Vn(()=>n.map((r,i)=>Mr(r,i,e.spriteOk)),[s])}function Ke({box:e}){if(!e)return null;let t=n=>{n.target===n.currentTarget&&ee()};return a`<div id="lightbox" class="lightbox" role="dialog" aria-label=${e.name} onClick=${t}>\n <button type="button" class="lbclose" title="close" onClick=${ee}>\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 be=a`<span class="x" onClick=${te}>\xD7</span>`,ys=(e,t,n)=>a`<span class="seg">${t.map(([s,r])=>a`<button class=${s===n?"on":""} onClick=${()=>e(s)}>${r}</button>`)}</span>`;function Er(e,t){let n=ys(Cn,[["table","table"],["cards","cards"]],t.view),s=ys(Dn,[["on","on"],["off","off"]],t.lobs?"on":"off"),r=e.attentionError?e.attentionError:(e.attentionKinds||[]).join(" \\xB7 ");return[be,a`<h3>\u2699 settings <span class="dim" style="font-weight:normal">\xB7 this browser only</span></h3>`,a`<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 Lr(e,t){let n=oe(t.numbers,new Map(t.numbers.map((r,i)=>[r,t.titles[i]])),e.number),s=t.nextMergeable?[" \\xB7 ",a`<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 Nr=e=>t=>{t.preventDefault(),M("dispatch",e)};function Hr(e,t){let n=un(e,t),s=n.pr,r=n.stack,i=n.watch,o=je(s),c=n.chain.length?n.chain.flatMap((l,f)=>[f?" \\u2192 ":"",l.culled?a`<span class="dim">${l.id.slice(0,8)} (culled)</span>`:[a`<a href="#" onClick=${Nr(l.modalKey)}>${l.id.slice(0,8)}</a>`," ",a`<span class="dim">${l.verb}</span>`]]):a`<span class="dim">none</span>`,u=i?[a`<div>${i.key} \xB7 owner ${i.owner||"?"} \xB7 ${i.lastCheckedAt?["checked ",v(i.lastCheckedAt)," ago"]:"never checked"}</div>`,i.lastError&&a`<div class="bad">${i.lastError}</div>`,a`<div class="dim" style="font-size:11px;margin-top:4px">cursor</div>`,S(i.cursor)]:a`<div class="dim">no watch \u2014 <code>lobstah watch add ${s.url}</code> registers one</div>`;return[be,a`<h3>${He(s)} ${s.title||""} <span class=${"badge "+L(s.badge)}>${s.badge.text}</span>${s.draft&&s.badge.text!=="draft"&&[" ",a`<span class="badge pr-draft">draft</span>`]}</h3>`,a`<div class="sub">${s.repo} \xB7 ${s.state} \xB7 observed ${v(s.observedAt)} ago${s.gate&&" \\xB7 gate "+s.gate}</div>`,a`<div class="sec">checks</div><div>${me(s)}</div><div class="sec">review</div><div>${o||a`<span class="dim">no review yet</span>`}</div><div class="sec">merge</div><div>${he(s)}</div>${s.repairWait&&a`<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?Lr(s,r):a`<span class="dim">not stacked</span>`}</div><div class="sec">dispatch chain</div><div>${c}</div><div class="sec">watch</div>`,u]}var ws=(e,t)=>(e==="codex"?"codex resume ":"claude --resume ")+t;function Ur(e){let t=Date.now()-Date.parse(e.heartbeatAt)>18e5;return[be,a`<h3>\u26F5 ${e.man}</h3><div class="sub">helm of <b>${e.grounds}</b> (${(e.repos||[]).join(", ")})</div><div class="sub">${e.harness??"?"} \xB7 ${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>`,e.sessionId&&[a`<div class="sec">open this session</div>`,S(ws(e.harness,e.sessionId))],e.transcript&&[a`<div class="sec">transcript</div>`,S(e.transcript)]]}function jr(e){return[a`<div class="sec">report \xB7 ${e.title}</div>`,a`<div class="sub">${Ct(e)} \xB7 <a href=${C(e.key)} target="_blank" rel="noopener">open the report \u2197</a></div>`]}function Br(e,t){let n=e.claimedBy&&e.claimedBy.startsWith("wt:")?[a`<div class="sec">worked by trap</div>`,a`<div class="claimedby">claimed by ${Ne(e.claimedBy.slice(3))}</div>`,S(j(e.claimedBy)),a`<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 ${j(e.claimedBy)} "\u2026"</div>`]:[a`<div class="sec">open this session</div>`,S("lobstah attach "+e.id)];return[be,a`<h3>${e.id.slice(0,8)} <span class=${"badge v-"+e.verb}>${e.verb}</span></h3>`,a`<div class="sub">${e.repo} \xB7 ${e.lane} ${e.bucket} \xB7 ${v(e.verbAt)}${e.for&&[" \\xB7 ",fe(e)]} ${re(e)}</div>`,n,e.worktree&&[a`<div class="sec">worktree${e.worktreeOf?" (reused from "+e.worktreeOf.slice(0,8)+")":""}</div>`,S(e.worktree),e.worktreeKept&&a`<div class="dim" style="font-size:11px">kept: ${e.worktreeKept}</div>`],e.transcript&&[a`<div class="sec">transcript</div>`,S(e.transcript)],t&&jr(t),Qn(e)]}function Or(e){let t=ge(e),n=e.requested?[e.repo??""," \\xB7 ",e.harness??""," \\xB7 requested ",v(e.requested.at)," ago from the glass; the helm reserves it and starts its session."]: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(o=>a`<div key=${o.seq} class="loglines">${v(o.at)} ago \xB7 <b>${o.kind}</b> \u2014 ${o.text}</div>`):a`<div class="empty">none recorded</div>`,r=e.messages.length?e.messages.map(o=>a`<div key=${o.file} class=${"msg"+(o.from==="helm"?" from-helm":"")}><div class="hdr">from ${o.from} \xB7 ${o.at&&[v(o.at)," ago"]} \xB7 ${o.state==="pending"?a`<span class="warn">pending</span>`:a`<span class="ok">delivered</span>`}</div>${o.text}${o.attachments?.length?se(o.attachments,c=>sn(e.trapId,c)):""}</div>`):a`<div class="empty">none</div>`,i=e.catches.length?e.catches.map(o=>a`<div key=${o.lane+":"+o.id} class="catch"><div class="hdr"><b>${o.id.slice(0,8)}</b><span class=${"badge v-"+o.verb}>${o.verb}</span><span class="dim">${v(o.verbAt)}</span>${re(o)}</div><div class="loglines">${_t(o)}</div></div>`):a`<div class="empty">none yet</div>`;return[be,a`<h3>\u{1FAA4} ${e.label??`wt:${e.trapId}`} <span class="badge">${e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??"signed off"}</span></h3>`,e.worktree&&a`<div class="sub">${e.worktree}</div>`,a`<div class="sub">${n}</div>`,a`<div class="sec">window</div>`,z(e),J(e),e.live&&e.sessionId&&[a`<div class="sec">open this session</div>`,S(ws(e.harness,e.sessionId)),a`<div class="dim" style="font-size:11px">as registered at sign-on \u2014 a hookless enlistment may hold a made-up id</div>`],a`<div class="sec">lifecycle (${e.notices.length})</div>`,s,a`<div class="sec">messages (${e.messages.length})</div>`,r,a`<div class="sec">catches (${e.catches.length})</div>`,i]}function Gs({snapshot:e,modal:t,prefs:n}){if(!e||!t)return null;let s=Y(e,t);if(!s)return null;if(t.type==="settings")return Er(s,n);if(t.type==="pr")return Hr(e,t.key);if(t.type==="helm")return Ur(s);if(t.type==="dispatch"){let r=an(e,s);return Br(s,r)}return Or(s)}var qr=e=>a`<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>`,xs=({inp:e})=>R(["at","kind","text","repo"],e.list.map(qr),"no notices");function Ts(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 Ss=(e,t)=>oe(e.numbers,new Map(t.map(n=>[n.number,n.title]))),Rt=e=>e.state+(e.draft?" \\xB7 draft":"")+(e.state==="MERGED"&&e.mergedAt?" \\xB7 "+e.mergedAt:"");function Cs(e){let t=s=>{let r=String(s??"");return r.length>24?r.slice(0,23)+"\\u2026":r},n=e.watches.map(s=>a`<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[a`<h2>other watches</h2>`,R(["key","owner","cursor","last check","error"],n,"no other watches")]}function Fr(e){let t=Ts(e).flatMap(({s:n,prs:s})=>[a`<tr key=${"stack:"+n.id}><th colspan="8">${Ss(n,s)} \xB7 floor ${n.floor}${n.open?" \\xB7 open":" \\xB7 history"}</th></tr>`,...s.map(r=>a`<tr key=${r.key} class="rowhead" onClick=${w("pr",r.key)}><td>${He(r)}</td><td class="grow">${r.title||""}</td><td>${Rt(r)}</td><td>${me(r)}</td><td>${je(r)}</td><td>${he(r)}</td><td>${bt(r.watch)}</td><td>${r.gate||""}</td></tr>`)]);return[R(["PR","title","state","checks","review","merge","watch","gate"],t,"no PR evidence"),Cs(e)]}function Wr(e){let t=Ts(e),n=r=>a`<div key=${r.key} class="card" onClick=${w("pr",r.key)}><div class="top">${Ue(r)}<span class=${"badge "+L(r.badge)+U(r.badge.text)} title=${H(r.badge.text)}>${r.badge.text}</span></div><div class="meta" title=${`${r.repo} \\xB7 ${Rt(r)}`}>${r.repo} \xB7 ${Rt(r)} \xB7 ${he(r)}</div><div class="foot"><span>${me(r)}</span><span>${bt(r.watch)}</span>${r.gate&&a`<span>gate ${r.gate}</span>`}</div></div>`;return[t.length?t.map(({s:r,prs:i})=>a`<${Z} key=${"stack:"+r.id}><h2>${Ss(r,i)} \xB7 floor ${r.floor}${r.open?"":" \\xB7 history"}</h2><div class="cards">${i.map(n)}</div><//>`):a`<div class="empty">no PR evidence</div>`,Cs(e)]}var Ds=({inp:e})=>e.view==="cards"?Wr(e):Fr(e);var Pt=e=>e.requested?"requested":e.starting?e.starting.failedAt?"start failed":"starting":e.harness??(e.live?"":"signed off"),As=e=>e.live||e.starting?"":" dim";function Vr(e){let t=ge(e);return a`<tr key=${e.trapId} class=${"rowhead"+As(e)} onClick=${w("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??""}</td><td>${(e.sessionId??"").slice(0,8)}</td><td>${ve(e)}${J(e)}</td><td>${t.listen}</td><td>${t.hb}</td><td>${yt(e)}</td><td>${e.catches.length}</td><td>${z(e)}</td></tr>`}function Kr(e){let t=ge(e),n=yt(e),s=`${e.repo??(e.live?"addressed bait only":"history")}${e.sessionId?" \\xB7 session "+e.sessionId.slice(0,8):""}`;return a`<div key=${e.trapId} class=${"card"+As(e)} onClick=${w("trap",e.trapId)}><div class="top"><b>\u{1FAA4} ${e.label??`wt:${e.trapId}`}</b><span class=${"badge"+U(Pt(e))} title=${H(Pt(e))}>${Pt(e)}</span></div><div class="meta" title=${s}>${s}</div>${e.worktree&&a`<div class="note" title=${e.worktree}>${e.worktree}</div>`}<div class="note" title=${Oe(e)}>${ve(e)}</div>${J(e)}<div class="foot"><span>${t.listen}${e.live&&[" \\xB7 heartbeat ",t.hb]} \xB7 ${e.catches.length} catch${e.catches.length===1?"":"es"}${n&&[" \\xB7 ",n]}</span><span class="footact">${z(e)}</span></div></div>`}function Rs({inp:e}){let t=e.list.map(s=>s.x),n=a`<div class="tabhead"><${Be} /></div>`;return e.view==="cards"?[n,t.length?a`<div class="cards">${t.map(Kr)}</div>`:a`<div class="empty">no traps soaking</div>`]:[n,R(["address","repo","worktree","harness","session","now","listening","heartbeat","mail","catches","window"],t.map(Vr),"no traps soaking")]}function Ps({state:e}){let t=e.snapshot,n=e.route,s=t&&pn(t,{st:e.prefs,modal:e.modal},Date.now()),r=o=>!s||o!==n?null:o==="deck"?a`<${hs} inp=${s.deck} drafts=${e.drafts} focus=${e.focusDecision} extensions=${t?.answerLimits?.extensions??[]} />`:o==="dispatches"?a`<${gs} inp=${s.dispatches} />`:o==="traps"?a`<${Rs} inp=${s.traps} />`:o==="prs"?a`<${Ds} inp=${s.prs} />`:o==="reports"?a`<${ns} inp=${s.reports} />`:a`<${xs} inp=${s.notices} />`,i=o=>{o.target===o.currentTarget&&te()};return[a`<${vs} d=${t} inp=${s} tab=${n} st=${e.prefs} stale=${e.stale} />`,ce.map(o=>a`<main key=${o} id=${"page-"+o} class=${t&&o===n?"tabpage on":"tabpage"}><div id=${o}>${r(o)}</div></main>`),a`<footer id="foot"><${_s} d=${t} /></footer>`,a`<div id="lobs"><${ks} state=${e} /></div>`,a`<${Ke} box=${e.lightbox} />`,a`<div id="overlay" class=${e.modal&&t?"open":t?"":void 0} onClick=${i}><div class="modal" id="modalbox"><${Gs} snapshot=${t} modal=${e.modal} prefs=${e.prefs} /></div></div>`]}function zr({view:e}){if(e.state==="loading")return a`<main class="reportview"><div class="dim">loading\u2026</div></main>`;if(e.state==="error")return a`<main class="reportview"><div class="bad">${e.error}</div></main>`;let t=e.report;return a`<main class="reportview">\n <h1>${t.title}</h1>\n <${us} r=${t} text=${e.text!==void 0?{text:e.text}:{error:e.error}} />\n </main>`}function Is({view:e,box:t}){return[a`<${zr} view=${e} />`,a`<${Ke} box=${t} />`]}async function Ms(e){let t=encodeURIComponent(e),n;try{let s=await fetch(`/report/${t}/meta`);if(!s.ok)return{state:"error",error:`report not found (${s.status})`};n=JSON.parse(await s.text())}catch{return{state:"error",error:"report could not be read"}}try{let s=await fetch(dn(e));return s.ok?{state:"ready",report:n,text:await s.text()}:{state:"ready",report:n,error:`report not found (${s.status})`}}catch{return{state:"ready",report:n,error:"report could not be read"}}}var It=!1,ke=null;async function Mt(){if(!It){It=!0;try{let e=await fetch("/data");if(!e.ok)throw new Error(`/data answered ${e.status}`);ut(await e.json())}catch{Gn()}finally{It=!1}}}var Es=()=>{ke||(ke=setInterval(Mt,2e3))},Jr=()=>{ke&&clearInterval(ke),ke=null};function Ls(){document.addEventListener("visibilitychange",()=>{document.hidden?Jr():(Mt(),Es())}),Mt(),document.hidden||Es()}var Et=()=>nn(location.hash),Ns=e=>window.addEventListener("hashchange",()=>e(Et()));function Us(){let e=ln(location.hash);return e===null?!1:(location.replace(C(e)),!0)}var js=()=>({snapshot:void 0,route:Et(),prefs:mn(),modal:null,stale:!1,lobHidden:gn(),spriteOk:null,focusResults:{},preview:new URLSearchParams(location.search).has("lob"),drafts:{},focusDecision:ot(location.hash),lightbox:null}),Hs=cn(location.pathname);Hs!==null?Xr(Hs):Us()||Qr();function Xr(e){dt(js());let t={state:"loading"},n=()=>nt(Q(Is,{view:t,box:_().lightbox}),document.body);document.title="report \\xB7 lobstah glass",pt(n),n(),Ms(e).then(s=>{t=s,s.state==="ready"&&(document.title=`${s.report.title} \\xB7 lobstah glass`),n()}),document.addEventListener("keydown",s=>{s.key==="Escape"&&_().lightbox&&ee()})}function Qr(){dt(js());let e,t=!1,n=()=>{let o=_(),c=o.route!==e||!t&&!!o.snapshot;nt(Q(Ps,{state:o}),document.body),e=o.route,t||(t=!!o.snapshot),c&&window.scrollTo(0,0),o.focusDecision||(s=null),r(o.focusDecision)},s=null;function r(o){if(!o||o===s)return;let c=[...document.querySelectorAll("[data-decision]")].find(u=>u.getAttribute("data-decision")===o);c&&(s=o,c.scrollIntoView?.({block:"center"}))}pt(n),n();let i=new Image;i.onload=()=>T({spriteOk:!0}),i.onerror=()=>T({spriteOk:!1}),i.src="/lob-sprite.png",Ns(o=>{if(Us())return;let c=ot(location.hash);c!==_().focusDecision&&(s=null),T({route:o,focusDecision:c})}),document.addEventListener("keydown",o=>{o.key==="Escape"&&(_().lightbox?ee():te())}),Ls()}})();</script>\n </body>\n</html>\n';
|
|
13244
13274
|
|
|
13245
13275
|
// apps/cli/src/glass-snapshot-thread.ts
|
|
13246
13276
|
init_dist2();
|
|
@@ -13389,7 +13419,7 @@ async function focusRegistration(reg, options = {}) {
|
|
|
13389
13419
|
return { focused: false, reason: "Invalid recorded WezTerm pane." };
|
|
13390
13420
|
if (win?.bundleId && VSCODE_RE.test(win.bundleId) && !safeWorktree(reg))
|
|
13391
13421
|
return { focused: false, reason: "Recorded editor worktree does not match this trap." };
|
|
13392
|
-
if (validSessionLink(reg.link)) {
|
|
13422
|
+
if (validSessionLink(reg.link) && linkMismatch(reg.link, win) === void 0) {
|
|
13393
13423
|
const opener = platform === "darwin" ? ["open", [reg.link]] : platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", reg.link]] : ["xdg-open", [reg.link]];
|
|
13394
13424
|
const result = await attempt(opener[0], opener[1], "link", "Opened the session link.");
|
|
13395
13425
|
if (result) return result;
|
|
@@ -13585,6 +13615,9 @@ function attentionSnapshot() {
|
|
|
13585
13615
|
return { attention: [], landed: [], attentionKinds: [], attentionError: err instanceof Error ? err.message : String(err) };
|
|
13586
13616
|
}
|
|
13587
13617
|
}
|
|
13618
|
+
function reportRow(key) {
|
|
13619
|
+
return reportRows2().find((r) => r.key === key);
|
|
13620
|
+
}
|
|
13588
13621
|
function reportRows2() {
|
|
13589
13622
|
return listReports().map((r) => {
|
|
13590
13623
|
const acked = reportAck(r);
|
|
@@ -13606,6 +13639,7 @@ function reportRows2() {
|
|
|
13606
13639
|
};
|
|
13607
13640
|
});
|
|
13608
13641
|
}
|
|
13642
|
+
var REPORT_PAGE_RE = /^\/report\/([^/?#]+)(\/meta)?\/?$/;
|
|
13609
13643
|
var REPORT_IMAGE_TYPES = {
|
|
13610
13644
|
".png": "image/png",
|
|
13611
13645
|
".jpg": "image/jpeg",
|
|
@@ -13751,7 +13785,9 @@ function buildGlassSnapshot(options = {}) {
|
|
|
13751
13785
|
...t,
|
|
13752
13786
|
name,
|
|
13753
13787
|
label: trapLabel({ trapId: t.trapId, name }),
|
|
13754
|
-
link
|
|
13788
|
+
// A link that contradicts the trap's window (a vscode:// link on a
|
|
13789
|
+
// terminal session) is not shown; focus falls back to the window.
|
|
13790
|
+
link: validSessionLink(t.link) && linkMismatch(t.link, t.window) === void 0 ? t.link : void 0,
|
|
13755
13791
|
sessionId: t.sessionId ?? signed?.by,
|
|
13756
13792
|
harness: t.harness ?? /\((claude|codex),/.exec(signed?.text ?? "")?.[1],
|
|
13757
13793
|
live: registered,
|
|
@@ -13969,6 +14005,27 @@ function serveGlass(port, options = {}) {
|
|
|
13969
14005
|
res.writeHead(200, { "content-type": "image/svg+xml", "cache-control": "no-cache" });
|
|
13970
14006
|
res.end(fallbackIcon);
|
|
13971
14007
|
}
|
|
14008
|
+
} else if (req.method === "GET" && REPORT_PAGE_RE.test(req.url?.split("?")[0] ?? "")) {
|
|
14009
|
+
if (req.headers.host !== ownHost()) {
|
|
14010
|
+
res.writeHead(403, { "content-type": "text/plain; charset=utf-8", "cache-control": "no-store" });
|
|
14011
|
+
res.end("Not this glass.");
|
|
14012
|
+
return;
|
|
14013
|
+
}
|
|
14014
|
+
const m = REPORT_PAGE_RE.exec(req.url.split("?")[0]);
|
|
14015
|
+
let key;
|
|
14016
|
+
try {
|
|
14017
|
+
key = decodeURIComponent(m[1]);
|
|
14018
|
+
} catch {
|
|
14019
|
+
key = "";
|
|
14020
|
+
}
|
|
14021
|
+
const row = key ? reportRow(key) : void 0;
|
|
14022
|
+
if (m[2] === "/meta") {
|
|
14023
|
+
res.writeHead(row ? 200 : 404, { "content-type": "application/json", "cache-control": "no-store" });
|
|
14024
|
+
res.end(JSON.stringify(row ?? { error: "report not found" }));
|
|
14025
|
+
return;
|
|
14026
|
+
}
|
|
14027
|
+
res.writeHead(row ? 200 : 404, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
14028
|
+
res.end(PAGE);
|
|
13972
14029
|
} else if ((req.url?.startsWith("/report/") || req.url?.startsWith("/decision/")) && req.method === "GET" && serveReport(req.url, res)) {
|
|
13973
14030
|
return;
|
|
13974
14031
|
} else if (req.url?.startsWith("/attachment/") && req.method === "GET" && serveAttachment(req.url, res)) {
|
|
@@ -16948,6 +17005,9 @@ ${usageFor("soak")}`
|
|
|
16948
17005
|
...reservation ? { trapId: reservation.trapId } : {}
|
|
16949
17006
|
}) : void 0;
|
|
16950
17007
|
if (made) worktree = canon(made.dir);
|
|
17008
|
+
const window = captureWindow();
|
|
17009
|
+
const linkFlag = opt("--link");
|
|
17010
|
+
const linkIgnored = linkFlag !== void 0 ? linkMismatch(linkFlag, window) : void 0;
|
|
16951
17011
|
let res;
|
|
16952
17012
|
try {
|
|
16953
17013
|
res = signOnTrap({
|
|
@@ -16958,8 +17018,8 @@ ${usageFor("soak")}`
|
|
|
16958
17018
|
sessionId,
|
|
16959
17019
|
one: has("--one") || void 0,
|
|
16960
17020
|
name: opt("--name"),
|
|
16961
|
-
window
|
|
16962
|
-
link:
|
|
17021
|
+
window,
|
|
17022
|
+
link: linkIgnored ? void 0 : linkFlag,
|
|
16963
17023
|
...reservation ? { trapId: reservation.trapId } : {},
|
|
16964
17024
|
ttlMs: cfg.soak.ttlSecs * 1e3
|
|
16965
17025
|
});
|
|
@@ -16992,6 +17052,7 @@ ${usageFor("soak")}`
|
|
|
16992
17052
|
repo: reg.repo ?? "(none configured \u2014 addressed work only)",
|
|
16993
17053
|
worktree: reg.worktree,
|
|
16994
17054
|
...made ? { created: true, branch: made.branch } : {},
|
|
17055
|
+
...linkIgnored ? { link: `ignored \u2014 ${linkIgnored}` } : {},
|
|
16995
17056
|
...reservation ? { ticket: `redeemed \u2014 signed on as the reserved trap` } : {},
|
|
16996
17057
|
...titled?.named ? { terminal: `tab named ${reg.name}` } : {},
|
|
16997
17058
|
...reg.one ? { one: true } : {},
|
|
@@ -66,6 +66,8 @@ For the glass's ↗ open button, give the trap its own session link with
|
|
|
66
66
|
`claude://claude.ai/...` link in the app; copy that link from the session.
|
|
67
67
|
Its app id is not the CLI session id. In the VS Code extension, use
|
|
68
68
|
`vscode://anthropic.claude-code/open?session=<session-id>` with the id above.
|
|
69
|
+
A CLI session in a terminal, including the Claude desktop app's terminal
|
|
70
|
+
panel, passes no link; soak ignores a link that does not fit the session.
|
|
69
71
|
The glass checks the stored link before showing it. `lobstah focus <trap>`
|
|
70
72
|
uses the same focus steps from the terminal.
|
|
71
73
|
|
package/docs/harness/codex.md
CHANGED
|
@@ -124,9 +124,10 @@ Codex task ids are UUIDv7 (for example `01a0ceb8-b9bd-7d42-…`); Claude Code
|
|
|
124
124
|
session ids are UUIDv4. When both harnesses' variables are set, lobstah uses
|
|
125
125
|
this format to tell which one signed on.
|
|
126
126
|
|
|
127
|
-
For the glass's ↗ open button
|
|
128
|
-
task id in the session-start brief and
|
|
129
|
-
`lobstah soak --link <url>`.
|
|
127
|
+
For the glass's ↗ open button in the Codex desktop app, form
|
|
128
|
+
`codex://threads/<task-id>` from the task id in the session-start brief and
|
|
129
|
+
pass it with `lobstah soak --link <url>`. A Codex CLI session in a terminal
|
|
130
|
+
passes no link; soak ignores a link that does not fit the session. The glass checks the stored link before
|
|
130
131
|
showing it. `lobstah focus <trap>` uses the same focus steps from the
|
|
131
132
|
terminal.
|
|
132
133
|
|
package/docs/man.md
CHANGED
|
@@ -462,9 +462,10 @@ the helm files to keep.
|
|
|
462
462
|
unacked first, up to 8, then "+N more", which opens the Reports tab. A
|
|
463
463
|
report's card or row shows its title, then who filed it (a trap's name, a
|
|
464
464
|
headless dispatch's id, nothing for the helm), its age, and `acked`. A
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
465
|
+
report opens on its own page, `/report/<key>`, in a new tab: from its card
|
|
466
|
+
or row, a lob, the desktop pet, or its dispatch's modal. The page renders
|
|
467
|
+
once and does not refresh; opening it does not ack the report.
|
|
468
|
+
`#report/<key>` goes to that page. The page shows headings, lists,
|
|
468
469
|
tables, fenced code, links (in a new tab), bold, italics, and images.
|
|
469
470
|
Raw HTML in the markdown shows as text. The glass serves the markdown and
|
|
470
471
|
the images read-only, and an image only by basename from that report's
|
|
@@ -558,9 +559,11 @@ the same rule.
|
|
|
558
559
|
[--text <text>] [--attach <file>]...` answers the same way, with the same
|
|
559
560
|
checks.
|
|
560
561
|
- **The pet.** The desktop pet shows a decision as its title only. A click
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
the
|
|
562
|
+
brings up the live helm's session through the pet's focus ladder: the
|
|
563
|
+
Claude desktop app for a desktop helm, the exact terminal tab for a terminal
|
|
564
|
+
helm. With no live helm, it opens the glass at the card. Either way it acks
|
|
565
|
+
the item for the pet (`lobstah attention ack <key> --by pet`). The card
|
|
566
|
+
stays in the glass until the decision is answered or withdrawn.
|
|
564
567
|
- **Cull.** `lobstah cull` removes a decision once its answer is older than
|
|
565
568
|
the retention window, with the `decision-answer` request and its files. A
|
|
566
569
|
standing decision is never culled.
|
|
@@ -806,7 +809,15 @@ lobstah soak --name amber-gull # choose or change this trap's two-word name
|
|
|
806
809
|
a VS Code extension URL of the form
|
|
807
810
|
`vscode://anthropic.claude-code/open?session=<id>`, or a Codex task URL of
|
|
808
811
|
the form `codex://threads/<task-id>`. It rejects all other schemes and
|
|
809
|
-
malformed links.
|
|
812
|
+
malformed links. A link must also fit the session's surface, taken from
|
|
813
|
+
Claude Code's `CLAUDE_CODE_ENTRYPOINT` and the recorded window: a `vscode://`
|
|
814
|
+
link only in the VS Code extension (`claude-vscode`), a `claude://` link only
|
|
815
|
+
in the Claude desktop app's Code tab, a `codex://` link only in the Codex app.
|
|
816
|
+
A CLI session in a terminal, including the Claude desktop app's terminal
|
|
817
|
+
panel, has no link: soak ignores one and prints `link: ignored — <why>`. The
|
|
818
|
+
glass and `lobstah focus` skip a stored link that contradicts the trap's
|
|
819
|
+
window and focus the window instead. The glass checks a stored link again
|
|
820
|
+
before rendering it.
|
|
810
821
|
`lobstah focus <trap>` accepts the trap id with or without `wt:` and reports
|
|
811
822
|
the focus step or why it could not focus. It does not revive a signed-off trap.
|
|
812
823
|
|