linear-grab 0.20.1 → 0.20.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/README.md CHANGED
@@ -26,7 +26,7 @@ export default function RootLayout({ children }) {
26
26
  {children}
27
27
  {process.env.NODE_ENV === "development" && (
28
28
  <Script
29
- src="https://cdn.jsdelivr.net/gh/ahmedbanihanibh/linear-grab@v0.20.1/dist/index.global.js"
29
+ src="https://cdn.jsdelivr.net/gh/ahmedbanihanibh/linear-grab@v0.20.2/dist/index.global.js"
30
30
  crossOrigin="anonymous"
31
31
  strategy="afterInteractive"
32
32
  />
@@ -16,7 +16,7 @@ import { createServer } from 'node:http';
16
16
  import { spawn, execFile } from 'node:child_process';
17
17
  import { randomUUID } from 'node:crypto';
18
18
  import { createHash } from 'node:crypto';
19
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
19
+ import { appendFileSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
20
20
  import { homedir } from 'node:os';
21
21
  import { join } from 'node:path';
22
22
 
@@ -28,7 +28,7 @@ const flag = (name, fallback) => {
28
28
  const PORT = Number(flag('--port', '4577'));
29
29
  const DIR = flag('--dir', process.cwd());
30
30
  const CLAUDE_BIN = flag('--claude', 'claude');
31
- const VERSION = '0.22.0';
31
+ const VERSION = '0.23.0';
32
32
 
33
33
  /** Best-effort command runner (git/gh introspection). Never throws. */
34
34
  function run(cmd, args, cwd = DIR) {
@@ -629,6 +629,106 @@ createServer(async (req, res) => {
629
629
  );
630
630
  return json(res, 200, { statuses, previews });
631
631
  }
632
+ // ---- react-scan telemetry -------------------------------------------
633
+ // Browser pushes render/interaction events; they land in an append-only
634
+ // NDJSON file agents read directly (.lineargrab/scan.ndjson at the repo).
635
+ if (req.method === 'POST' && url.pathname === '/scan/events') {
636
+ const body = await readBody(req);
637
+ const events = Array.isArray(body.events) ? body.events : [body];
638
+ const dir = join(DIR, '.lineargrab');
639
+ try {
640
+ mkdirSync(dir, { recursive: true });
641
+ // Self-ignoring: telemetry must never pollute commits.
642
+ writeFileSync(join(dir, '.gitignore'), '*\n', { flag: 'wx' });
643
+ } catch {
644
+ /* exists */
645
+ }
646
+ const file = join(dir, 'scan.ndjson');
647
+ const lines =
648
+ events
649
+ .slice(0, 200)
650
+ .map((e) => JSON.stringify({ at: Date.now(), ...e }))
651
+ .join('\n') + '\n';
652
+ try {
653
+ appendFileSync(file, lines);
654
+ // Rotation: cap ~2MB by keeping the newest half.
655
+ const size = statSync(file).size;
656
+ if (size > 2_000_000) {
657
+ const keep = readFileSync(file, 'utf8');
658
+ writeFileSync(file, keep.slice(Math.floor(keep.length / 2)).replace(/^[^\n]*\n/, ''));
659
+ }
660
+ } catch {
661
+ /* disk issues — telemetry must never error the page */
662
+ }
663
+ return json(res, 200, { ok: true });
664
+ }
665
+ // Aggregated "what's slow right now" — a convenience view over the file.
666
+ if (req.method === 'GET' && url.pathname === '/scan/report') {
667
+ const windowMs = Number(url.searchParams.get('window') ?? 120_000);
668
+ let raw = '';
669
+ try {
670
+ raw = readFileSync(join(DIR, '.lineargrab', 'scan.ndjson'), 'utf8');
671
+ } catch {
672
+ return json(res, 200, { report: 'No scan telemetry yet — is react-scan running with the bridge enabled?', components: [] });
673
+ }
674
+ const cutoff = Date.now() - windowMs;
675
+ const byComponent = new Map();
676
+ const interactions = [];
677
+ for (const line of raw.split('\n')) {
678
+ if (!line) continue;
679
+ let e;
680
+ try {
681
+ e = JSON.parse(line);
682
+ } catch {
683
+ continue;
684
+ }
685
+ if ((e.at ?? 0) < cutoff) continue;
686
+ if (e.kind === 'interaction') interactions.push(e);
687
+ for (const c of e.components ?? []) {
688
+ const cur = byComponent.get(c.name) ?? {
689
+ name: c.name,
690
+ renders: 0,
691
+ selfTime: 0,
692
+ source: c.source ?? null,
693
+ unnecessary: 0,
694
+ changes: {},
695
+ };
696
+ cur.renders += c.renders ?? 1;
697
+ cur.selfTime += c.selfTime ?? 0;
698
+ if (c.source) cur.source = c.source;
699
+ if (c.unnecessary) cur.unnecessary += c.renders ?? 1;
700
+ for (const ch of c.changes ?? []) cur.changes[ch] = (cur.changes[ch] ?? 0) + 1;
701
+ byComponent.set(c.name, cur);
702
+ }
703
+ }
704
+ const components = [...byComponent.values()].sort((a, b) => b.selfTime - a.selfTime).slice(0, 25);
705
+ const md = [
706
+ `# react-scan report (last ${Math.round(windowMs / 1000)}s)`,
707
+ '',
708
+ ...components.map(
709
+ (c) =>
710
+ `- **${c.name}** — ${c.renders} renders · ${c.selfTime.toFixed(1)}ms self` +
711
+ (c.unnecessary ? ` · ${c.unnecessary} unnecessary` : '') +
712
+ (c.source ? ` · \`${c.source}\`` : '') +
713
+ (Object.keys(c.changes).length
714
+ ? ` · causes: ${Object.entries(c.changes)
715
+ .sort((a, b) => b[1] - a[1])
716
+ .slice(0, 3)
717
+ .map(([k, v]) => `${k}×${v}`)
718
+ .join(', ')}`
719
+ : ''),
720
+ ),
721
+ '',
722
+ ...interactions
723
+ .slice(-10)
724
+ .map(
725
+ (i) =>
726
+ `- interaction ${i.type ?? '?'} on ${i.target ?? '?'} — ${Math.round(i.duration ?? 0)}ms` +
727
+ (i.slow ? ' ⚠ SLOW' : ''),
728
+ ),
729
+ ].join('\n');
730
+ return json(res, 200, { report: md, components, interactions: interactions.slice(-20) });
731
+ }
632
732
  // Reset the staging branch: delete + recreate from the default branch.
633
733
  if (req.method === 'POST' && url.pathname === '/branch/reset') {
634
734
  const body = await readBody(req);
@@ -117,7 +117,7 @@ Summary (description field) → Steps to Reproduce (reproSteps) → Expected Beh
117
117
  (analysisNotes, markdown bullets grounded in the provided source context) →
118
118
  Suggested Next Steps (suggestedNextSteps, markdown bullets with concrete fixes).
119
119
  The Summary is a short plain-prose paragraph — no headings inside it, no repetition
120
- of the other sections.`,hD="- FIRST, self-orient in the repo checkout (skip any path that doesn't exist):\n 1. Read `CLAUDE.md` and `AGENTS.md` at the repo root — the master map of product rules, architecture, and memory/skill pointers.\n 2. Skim `.claude/memory/MEMORY.md` (the index) to learn what project memory exists; load the specific `.claude/memory/*.md` files the map names for the surface you're touching.\n 3. Load the matching `.claude/skills/<name>/SKILL.md` files before designing, building UI, or animating (if skills are symlinked, follow them into `.agents/skills/`).\n Treat all of this as authoritative — it overrides your defaults.\n- Keep going until the code works and you're happy with the implementation.\n- MANDATORY COMPLETION GATE — the task is NOT complete (and you may not call it complete) until every step below is done, in order. Skipping any step silently is a FAILED task:\n 1. RUN the app and TEST your change hands-on (computer use / a real browser against the running app). Code reading alone does not count as verification.\n 2. RECORD a demo video or GIF showing the fix working (before → after where possible). If your environment genuinely cannot record media, capture before/after screenshots instead AND state explicitly in your closeout comment why video was not possible — never just omit the demo.\n 3. Open the PR, babysit it for the first set of review comments, and address them. If the repo has preview deployments (e.g. Vercel), wait for the preview to go green and include its URL — deep-linked to the changed page — in the PR body, the Linear closeout, and the announcement.\n 4. CLOSE OUT THE LINEAR ISSUE: post a completion comment (one-line fix summary + PR link), attach the demo media to the ISSUE itself (not only the PR), and move the issue to its review/done state."})),_D=r({describeAiError:()=>bD,executeDraft:()=>vD});async function vD(e,t,n){let r=await jx(e.tier);try{return await yD(r,e,t,n,!1)}catch(i){if(n.aborted)throw i;let a=await Mx(r.provider,e.tier);if(!a)throw Error(bD(i));try{return await yD(a,e,t,n,!0)}catch(e){throw Error(bD(e))}}}async function yD(e,t,n,r,i){let a=bT({model:e.model,schema:sD,system:mD,prompt:dD(t),abortSignal:r});for await(let e of a.partialObjectStream)n(e);return{draft:await a.object,provider:e.provider,modelId:e.modelId,fellBack:i}}function bD(e){let t=e instanceof Error?e.message:String(e);return/401|unauthorized|invalid.*key/i.test(t)?`AI provider rejected the API key.`:/429|rate/i.test(t)?`AI provider rate limit hit — try again shortly.`:`Draft failed: ${t}`}var xD=t((()=>{aD(),cD(),gD(),Fx()}));Sr(),Fx();function SD(e,t){return xr?CD(e,t):wD(e,t)}function CD(e,t){let n=chrome.runtime.connect({name:`ai-draft`}),r=!1;return n.onMessage.addListener(e=>{e.type===`partial`?t.onPartial(e.draft):e.type===`done`?(r=!0,t.onDone(e),n.disconnect()):e.type===`error`&&(r=!0,t.onError(e.message,e.code===`no-provider`?`no-provider`:`unknown`),n.disconnect())}),n.onDisconnect.addListener(()=>{r||t.onError(`Draft stream disconnected.`)}),n.postMessage({type:`start`,input:e}),()=>{try{n.disconnect()}catch{}}}function wD(e,t){let n=new AbortController;return(async()=>{let{executeDraft:r}=await Promise.resolve().then(()=>(xD(),_D));try{let i=await r(e,t.onPartial,n.signal);n.signal.aborted||t.onDone(i)}catch(e){if(n.signal.aborted)return;t.onError(e instanceof Error?e.message:String(e),e instanceof Px?`no-provider`:`unknown`)}})(),()=>n.abort()}var TD=n((e=>{var t=Object.defineProperty;(e=>t(e,`__esModule`,{value:!0}))(e),((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(e,{GIFEncoder:()=>ee,applyPalette:()=>S,default:()=>le,nearestColor:()=>k,nearestColorIndex:()=>D,nearestColorIndexWithDistance:()=>O,prequantize:()=>x,quantize:()=>_,snapColorsToPalette:()=>T});var n={signature:`GIF`,version:`89a`,trailer:59,extensionIntroducer:33,applicationExtensionLabel:255,graphicControlExtensionLabel:249,imageSeparator:44,signatureSize:3,versionSize:3,globalColorTableFlagMask:128,colorResolutionMask:112,sortFlagMask:8,globalColorTableSizeMask:7,applicationIdentifierSize:8,applicationAuthCodeSize:3,disposalMethodMask:28,userInputFlagMask:2,transparentColorFlagMask:1,localColorTableFlagMask:128,interlaceFlagMask:64,idSortFlagMask:32,localColorTableSizeMask:7};function r(e=256){let t=0,n=new Uint8Array(e);return{get buffer(){return n.buffer},reset(){t=0},bytesView(){return n.subarray(0,t)},bytes(){return n.slice(0,t)},writeByte(e){r(t+1),n[t]=e,t++},writeBytes(e,i=0,a=e.length){r(t+a);for(let r=0;r<a;r++)n[t++]=e[r+i]},writeBytesView(e,i=0,a=e.byteLength){r(t+a),n.set(e.subarray(i,i+a),t),t+=a}};function r(e){var r=n.length;if(r>=e)return;e=Math.max(e,r*(r<1024*1024?2:1.125)>>>0),r!=0&&(e=Math.max(e,256));let i=n;n=new Uint8Array(e),t>0&&n.set(i.subarray(0,t),0)}}var i=12,a=5003,o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function s(e,t,n,s,c=r(512),l=new Uint8Array(256),u=new Int32Array(a),d=new Int32Array(a)){let f=u.length,p=Math.max(2,s);l.fill(0),d.fill(0),u.fill(-1);let m=0,h=0,g=p+1,_=g,v=!1,y=_,b=(1<<y)-1,x=1<<g-1,S=x+1,C=x+2,w=0,T=n[0],E=0;for(let e=f;e<65536;e*=2)++E;E=8-E,c.writeByte(p),O(x);let D=n.length;for(let e=1;e<D;e++)next_block:{let t=n[e],r=(t<<i)+T,a=t<<E^T;if(u[a]===r){T=d[a];break next_block}let o=a===0?1:f-a;for(;u[a]>=0;)if(a-=o,a<0&&(a+=f),u[a]===r){T=d[a];break next_block}O(T),T=t,C<1<<i?(d[a]=C++,u[a]=r):(u.fill(-1),C=x+2,v=!0,O(x))}return O(T),O(S),c.writeByte(0),c.bytesView();function O(e){for(m&=o[h],h>0?m|=e<<h:m=e,h+=y;h>=8;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;if((C>b||v)&&(v?(y=_,b=(1<<y)-1,v=!1):(++y,b=y===i?1<<y:(1<<y)-1)),e==S){for(;h>0;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;w>0&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0)}}}var c=s;function l(e,t,n){return e<<8&63488|t<<2&992|n>>3}function u(e,t,n,r){return e>>4|t&240|(n&240)<<4|(r&240)<<8}function d(e,t,n){return e>>4<<8|t&240|n>>4}function f(e,t,n){return e<t?t:e>n?n:e}function p(e){return e*e}function m(e,t,n){var r=0,i=1e100;let a=e[t],o=a.cnt,s=a.ac,c=a.rc,l=a.gc,u=a.bc;for(var d=a.fw;d!=0;d=e[d].fw){let t=e[d],a=t.cnt,m=o*a/(o+a);if(!(m>=i)){var f=0;n&&(f+=m*p(t.ac-s),f>=i)||(f+=m*p(t.rc-c),!(f>=i)&&(f+=m*p(t.gc-l),!(f>=i)&&(f+=m*p(t.bc-u),!(f>=i)&&(i=f,r=d))))}}a.err=i,a.nn=r}function h(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function g(e,t){let n=Array(t===`rgb444`?4096:65536),r=e.length;if(t===`rgba4444`)for(let t=0;t<r;++t){let r=e[t],i=r>>24&255,a=r>>16&255,o=r>>8&255,s=r&255,c=u(s,o,a,i),l=c in n?n[c]:n[c]=h();l.rc+=s,l.gc+=o,l.bc+=a,l.ac+=i,l.cnt++}else if(t===`rgb444`)for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=d(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}else for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=l(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}return n}function _(e,t,n={}){let{format:r=`rgb565`,clearAlpha:i=!0,clearAlphaColor:a=0,clearAlphaThreshold:o=0,oneBitAlpha:s=!1}=n;if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);let c=new Uint32Array(e.buffer),l=n.useSqrt!==!1,u=r===`rgba4444`,d=g(c,r),h=d.length,_=h-1,y=new Uint32Array(h+1);for(var b=0,x=0;x<h;++x){let e=d[x];if(e!=null){var S=1/e.cnt;u&&(e.ac*=S),e.rc*=S,e.gc*=S,e.bc*=S,d[b++]=e}}p(t)/b<.022&&(l=!1);for(var x=0;x<b-1;++x)d[x].fw=x+1,d[x+1].bk=x,l&&(d[x].cnt=Math.sqrt(d[x].cnt));l&&(d[x].cnt=Math.sqrt(d[x].cnt));var C,w,T;for(x=0;x<b;++x){m(d,x,!1);var E=d[x].err;for(w=++y[0];w>1&&(T=w>>1,!(d[C=y[T]].err<=E));w=T)y[w]=C;y[w]=x}var D=b-t;for(x=0;x<D;){for(var O;;){var k=y[1];if(O=d[k],O.tm>=O.mtm&&d[O.nn].mtm<=O.tm)break;O.mtm==_?k=y[1]=y[y[0]--]:(m(d,k,!1),O.tm=x);var E=d[k].err;for(w=1;(T=w+w)<=y[0]&&(T<y[0]&&d[y[T]].err>d[y[T+1]].err&&T++,!(E<=d[C=y[T]].err));w=T)y[w]=C;y[w]=k}var ee=d[O.nn],te=O.cnt,A=ee.cnt,S=1/(te+A);u&&(O.ac=S*(te*O.ac+A*ee.ac)),O.rc=S*(te*O.rc+A*ee.rc),O.gc=S*(te*O.gc+A*ee.gc),O.bc=S*(te*O.bc+A*ee.bc),O.cnt+=ee.cnt,O.mtm=++x,d[ee.bk].fw=ee.fw,d[ee.fw].bk=ee.bk,ee.mtm=_}let ne=[];var re=0;for(x=0;;++re){let e=f(Math.round(d[x].rc),0,255),t=f(Math.round(d[x].gc),0,255),n=f(Math.round(d[x].bc),0,255),r=255;u&&(r=f(Math.round(d[x].ac),0,255),s&&(r=r<=(typeof s==`number`?s:127)?0:255),i&&r<=o&&(e=t=n=a,r=0));let c=u?[e,t,n,r]:[e,t,n];if(v(ne,c)||ne.push(c),(x=d[x].fw)==0)break}return ne}function v(e,t){for(let n=0;n<e.length;n++){let r=e[n],i=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],a=r.length>=4&&t.length>=4?r[3]===t[3]:!0;if(i&&a)return!0}return!1}function y(e,t){var n=0,r;for(r=0;r<e.length;r++){let i=e[r]-t[r];n+=i*i}return n}function b(e,t){return t>1?Math.round(e/t)*t:e}function x(e,{roundRGB:t=5,roundAlpha:n=10,oneBitAlpha:r=null}={}){let i=new Uint32Array(e.buffer);for(let e=0;e<i.length;e++){let a=i[e],o=a>>24&255,s=a>>16&255,c=a>>8&255,l=a&255;o=b(o,n),r&&(o=o<=(typeof r==`number`?r:127)?0:255),l=b(l,t),c=b(c,t),s=b(s,t),i[e]=o<<24|s<<16|c<<8|l<<0}}function S(e,t,n=`rgb565`){if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);if(t.length>256)throw Error(`applyPalette() only works with 256 colors or less`);let r=new Uint32Array(e.buffer),i=r.length,a=n===`rgb444`?4096:65536,o=new Uint8Array(i),s=Array(a);if(n===`rgba4444`)for(let e=0;e<i;e++){let n=r[e],i=n>>24&255,a=n>>16&255,c=n>>8&255,l=n&255,d=u(l,c,a,i);o[e]=d in s?s[d]:s[d]=C(l,c,a,i,t)}else{let e=n===`rgb444`?d:l;for(let n=0;n<i;n++){let i=r[n],a=i>>16&255,c=i>>8&255,l=i&255,u=e(l,c,a);o[n]=u in s?s[u]:s[u]=w(l,c,a,t)}}return o}function C(e,t,n,r,i){let a=0,o=1e100;for(let s=0;s<i.length;s++){let c=i[s],l=c[3],u=E(l-r);if(u>o)continue;let d=c[0];if(u+=E(d-e),u>o)continue;let f=c[1];if(u+=E(f-t),u>o)continue;let p=c[2];u+=E(p-n),!(u>o)&&(o=u,a=s)}return a}function w(e,t,n,r){let i=0,a=1e100;for(let o=0;o<r.length;o++){let s=r[o],c=s[0],l=E(c-e);if(l>a)continue;let u=s[1];if(l+=E(u-t),l>a)continue;let d=s[2];l+=E(d-n),!(l>a)&&(a=l,i=o)}return i}function T(e,t,n=5){if(!e.length||!t.length)return;let r=e.map(e=>e.slice(0,3)),i=n*n,a=e[0].length;for(let n=0;n<t.length;n++){let o=t[n];o=o.length<a?[o[0],o[1],o[2],255]:o.length>a?o.slice(0,3):o.slice();let s=O(r,o.slice(0,3),y),c=s[0],l=s[1];l>0&&l<=i&&(e[c]=o)}}function E(e){return e*e}function D(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return i}function O(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return[i,r]}function k(e,t,n=y){return e[D(e,t,n)]}function ee(e={}){let{initialCapacity:t=4096,auto:i=!0}=e,a=r(t),o=5003,s=new Uint8Array(256),c=new Int32Array(o),l=new Int32Array(o),u=!1;return{reset(){a.reset(),u=!1},finish(){a.writeByte(n.trailer)},bytes(){return a.bytes()},bytesView(){return a.bytesView()},get buffer(){return a.buffer},get stream(){return a},writeHeader:d,writeFrame(e,t,n,r={}){let{transparent:o=!1,transparentIndex:f=0,delay:p=0,palette:m=null,repeat:h=0,colorDepth:g=8,dispose:_=-1}=r,v=!1;if(i?u||=(v=!0,d(),!0):v=!!r.first,t=Math.max(0,Math.floor(t)),n=Math.max(0,Math.floor(n)),v){if(!m)throw Error(`First frame must include a { palette } option`);A(a,t,n,m,g),re(a,m),h>=0&&ne(a,h)}let y=Math.round(p/10);te(a,_,y,o,f);let b=!!m&&!v;ie(a,t,n,b?m:null),b&&re(a,m),ae(a,e,t,n,g,s,c,l)}};function d(){se(a,`GIF89a`)}}function te(e,t,n,r,i){e.writeByte(33),e.writeByte(249),e.writeByte(4),i<0&&(i=0,r=!1);var a,o;r?(a=1,o=2):(a=0,o=0),t>=0&&(o=t&7),o<<=2,e.writeByte(o|0|a),oe(e,n),e.writeByte(i||0),e.writeByte(0)}function A(e,t,n,r,i=8){let a=ce(r.length)-1,o=i-1<<4|128|a;oe(e,t),oe(e,n),e.writeBytes([o,0,0])}function ne(e,t){e.writeByte(33),e.writeByte(255),e.writeByte(11),se(e,`NETSCAPE2.0`),e.writeByte(3),e.writeByte(1),oe(e,t),e.writeByte(0)}function re(e,t){let n=1<<ce(t.length);for(let r=0;r<n;r++){let n=[0,0,0];r<t.length&&(n=t[r]),e.writeByte(n[0]),e.writeByte(n[1]),e.writeByte(n[2])}}function ie(e,t,n,r){if(e.writeByte(44),oe(e,0),oe(e,0),oe(e,t),oe(e,n),r){let t=ce(r.length)-1;e.writeByte(128|t)}else e.writeByte(0)}function ae(e,t,n,r,i=8,a,o,s){c(n,r,t,i,e,a,o,s)}function oe(e,t){e.writeByte(t&255),e.writeByte(t>>8&255)}function se(e,t){for(var n=0;n<t.length;n++)e.writeByte(t.charCodeAt(n))}function ce(e){return Math.max(Math.ceil(Math.log2(e)),1)}var le=ee}))(),ED="(function(){var e=((e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports))((e=>{var t=Object.defineProperty;(e=>t(e,`__esModule`,{value:!0}))(e),((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(e,{GIFEncoder:()=>A,applyPalette:()=>S,default:()=>B,nearestColor:()=>k,nearestColorIndex:()=>D,nearestColorIndexWithDistance:()=>O,prequantize:()=>x,quantize:()=>_,snapColorsToPalette:()=>T});var n={signature:`GIF`,version:`89a`,trailer:59,extensionIntroducer:33,applicationExtensionLabel:255,graphicControlExtensionLabel:249,imageSeparator:44,signatureSize:3,versionSize:3,globalColorTableFlagMask:128,colorResolutionMask:112,sortFlagMask:8,globalColorTableSizeMask:7,applicationIdentifierSize:8,applicationAuthCodeSize:3,disposalMethodMask:28,userInputFlagMask:2,transparentColorFlagMask:1,localColorTableFlagMask:128,interlaceFlagMask:64,idSortFlagMask:32,localColorTableSizeMask:7};function r(e=256){let t=0,n=new Uint8Array(e);return{get buffer(){return n.buffer},reset(){t=0},bytesView(){return n.subarray(0,t)},bytes(){return n.slice(0,t)},writeByte(e){r(t+1),n[t]=e,t++},writeBytes(e,i=0,a=e.length){r(t+a);for(let r=0;r<a;r++)n[t++]=e[r+i]},writeBytesView(e,i=0,a=e.byteLength){r(t+a),n.set(e.subarray(i,i+a),t),t+=a}};function r(e){var r=n.length;if(r>=e)return;e=Math.max(e,r*(r<1024*1024?2:1.125)>>>0),r!=0&&(e=Math.max(e,256));let i=n;n=new Uint8Array(e),t>0&&n.set(i.subarray(0,t),0)}}var i=12,a=5003,o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function s(e,t,n,s,c=r(512),l=new Uint8Array(256),u=new Int32Array(a),d=new Int32Array(a)){let f=u.length,p=Math.max(2,s);l.fill(0),d.fill(0),u.fill(-1);let m=0,h=0,g=p+1,_=g,v=!1,y=_,b=(1<<y)-1,x=1<<g-1,S=x+1,C=x+2,w=0,T=n[0],E=0;for(let e=f;e<65536;e*=2)++E;E=8-E,c.writeByte(p),O(x);let D=n.length;for(let e=1;e<D;e++)next_block:{let t=n[e],r=(t<<i)+T,a=t<<E^T;if(u[a]===r){T=d[a];break next_block}let o=a===0?1:f-a;for(;u[a]>=0;)if(a-=o,a<0&&(a+=f),u[a]===r){T=d[a];break next_block}O(T),T=t,C<1<<i?(d[a]=C++,u[a]=r):(u.fill(-1),C=x+2,v=!0,O(x))}return O(T),O(S),c.writeByte(0),c.bytesView();function O(e){for(m&=o[h],h>0?m|=e<<h:m=e,h+=y;h>=8;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;if((C>b||v)&&(v?(y=_,b=(1<<y)-1,v=!1):(++y,b=y===i?1<<y:(1<<y)-1)),e==S){for(;h>0;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;w>0&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0)}}}var c=s;function l(e,t,n){return e<<8&63488|t<<2&992|n>>3}function u(e,t,n,r){return e>>4|t&240|(n&240)<<4|(r&240)<<8}function d(e,t,n){return e>>4<<8|t&240|n>>4}function f(e,t,n){return e<t?t:e>n?n:e}function p(e){return e*e}function m(e,t,n){var r=0,i=1e100;let a=e[t],o=a.cnt,s=a.ac,c=a.rc,l=a.gc,u=a.bc;for(var d=a.fw;d!=0;d=e[d].fw){let t=e[d],a=t.cnt,m=o*a/(o+a);if(!(m>=i)){var f=0;n&&(f+=m*p(t.ac-s),f>=i)||(f+=m*p(t.rc-c),!(f>=i)&&(f+=m*p(t.gc-l),!(f>=i)&&(f+=m*p(t.bc-u),!(f>=i)&&(i=f,r=d))))}}a.err=i,a.nn=r}function h(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function g(e,t){let n=Array(t===`rgb444`?4096:65536),r=e.length;if(t===`rgba4444`)for(let t=0;t<r;++t){let r=e[t],i=r>>24&255,a=r>>16&255,o=r>>8&255,s=r&255,c=u(s,o,a,i),l=c in n?n[c]:n[c]=h();l.rc+=s,l.gc+=o,l.bc+=a,l.ac+=i,l.cnt++}else if(t===`rgb444`)for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=d(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}else for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=l(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}return n}function _(e,t,n={}){let{format:r=`rgb565`,clearAlpha:i=!0,clearAlphaColor:a=0,clearAlphaThreshold:o=0,oneBitAlpha:s=!1}=n;if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);let c=new Uint32Array(e.buffer),l=n.useSqrt!==!1,u=r===`rgba4444`,d=g(c,r),h=d.length,_=h-1,y=new Uint32Array(h+1);for(var b=0,x=0;x<h;++x){let e=d[x];if(e!=null){var S=1/e.cnt;u&&(e.ac*=S),e.rc*=S,e.gc*=S,e.bc*=S,d[b++]=e}}p(t)/b<.022&&(l=!1);for(var x=0;x<b-1;++x)d[x].fw=x+1,d[x+1].bk=x,l&&(d[x].cnt=Math.sqrt(d[x].cnt));l&&(d[x].cnt=Math.sqrt(d[x].cnt));var C,w,T;for(x=0;x<b;++x){m(d,x,!1);var E=d[x].err;for(w=++y[0];w>1&&(T=w>>1,!(d[C=y[T]].err<=E));w=T)y[w]=C;y[w]=x}var D=b-t;for(x=0;x<D;){for(var O;;){var k=y[1];if(O=d[k],O.tm>=O.mtm&&d[O.nn].mtm<=O.tm)break;O.mtm==_?k=y[1]=y[y[0]--]:(m(d,k,!1),O.tm=x);var E=d[k].err;for(w=1;(T=w+w)<=y[0]&&(T<y[0]&&d[y[T]].err>d[y[T+1]].err&&T++,!(E<=d[C=y[T]].err));w=T)y[w]=C;y[w]=k}var A=d[O.nn],j=O.cnt,M=A.cnt,S=1/(j+M);u&&(O.ac=S*(j*O.ac+M*A.ac)),O.rc=S*(j*O.rc+M*A.rc),O.gc=S*(j*O.gc+M*A.gc),O.bc=S*(j*O.bc+M*A.bc),O.cnt+=A.cnt,O.mtm=++x,d[A.bk].fw=A.fw,d[A.fw].bk=A.bk,A.mtm=_}let N=[];var P=0;for(x=0;;++P){let e=f(Math.round(d[x].rc),0,255),t=f(Math.round(d[x].gc),0,255),n=f(Math.round(d[x].bc),0,255),r=255;u&&(r=f(Math.round(d[x].ac),0,255),s&&(r=r<=(typeof s==`number`?s:127)?0:255),i&&r<=o&&(e=t=n=a,r=0));let c=u?[e,t,n,r]:[e,t,n];if(v(N,c)||N.push(c),(x=d[x].fw)==0)break}return N}function v(e,t){for(let n=0;n<e.length;n++){let r=e[n],i=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],a=r.length>=4&&t.length>=4?r[3]===t[3]:!0;if(i&&a)return!0}return!1}function y(e,t){var n=0,r;for(r=0;r<e.length;r++){let i=e[r]-t[r];n+=i*i}return n}function b(e,t){return t>1?Math.round(e/t)*t:e}function x(e,{roundRGB:t=5,roundAlpha:n=10,oneBitAlpha:r=null}={}){let i=new Uint32Array(e.buffer);for(let e=0;e<i.length;e++){let a=i[e],o=a>>24&255,s=a>>16&255,c=a>>8&255,l=a&255;o=b(o,n),r&&(o=o<=(typeof r==`number`?r:127)?0:255),l=b(l,t),c=b(c,t),s=b(s,t),i[e]=o<<24|s<<16|c<<8|l<<0}}function S(e,t,n=`rgb565`){if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);if(t.length>256)throw Error(`applyPalette() only works with 256 colors or less`);let r=new Uint32Array(e.buffer),i=r.length,a=n===`rgb444`?4096:65536,o=new Uint8Array(i),s=Array(a);if(n===`rgba4444`)for(let e=0;e<i;e++){let n=r[e],i=n>>24&255,a=n>>16&255,c=n>>8&255,l=n&255,d=u(l,c,a,i);o[e]=d in s?s[d]:s[d]=C(l,c,a,i,t)}else{let e=n===`rgb444`?d:l;for(let n=0;n<i;n++){let i=r[n],a=i>>16&255,c=i>>8&255,l=i&255,u=e(l,c,a);o[n]=u in s?s[u]:s[u]=w(l,c,a,t)}}return o}function C(e,t,n,r,i){let a=0,o=1e100;for(let s=0;s<i.length;s++){let c=i[s],l=c[3],u=E(l-r);if(u>o)continue;let d=c[0];if(u+=E(d-e),u>o)continue;let f=c[1];if(u+=E(f-t),u>o)continue;let p=c[2];u+=E(p-n),!(u>o)&&(o=u,a=s)}return a}function w(e,t,n,r){let i=0,a=1e100;for(let o=0;o<r.length;o++){let s=r[o],c=s[0],l=E(c-e);if(l>a)continue;let u=s[1];if(l+=E(u-t),l>a)continue;let d=s[2];l+=E(d-n),!(l>a)&&(a=l,i=o)}return i}function T(e,t,n=5){if(!e.length||!t.length)return;let r=e.map(e=>e.slice(0,3)),i=n*n,a=e[0].length;for(let n=0;n<t.length;n++){let o=t[n];o=o.length<a?[o[0],o[1],o[2],255]:o.length>a?o.slice(0,3):o.slice();let s=O(r,o.slice(0,3),y),c=s[0],l=s[1];l>0&&l<=i&&(e[c]=o)}}function E(e){return e*e}function D(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return i}function O(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return[i,r]}function k(e,t,n=y){return e[D(e,t,n)]}function A(e={}){let{initialCapacity:t=4096,auto:i=!0}=e,a=r(t),o=5003,s=new Uint8Array(256),c=new Int32Array(o),l=new Int32Array(o),u=!1;return{reset(){a.reset(),u=!1},finish(){a.writeByte(n.trailer)},bytes(){return a.bytes()},bytesView(){return a.bytesView()},get buffer(){return a.buffer},get stream(){return a},writeHeader:d,writeFrame(e,t,n,r={}){let{transparent:o=!1,transparentIndex:f=0,delay:p=0,palette:m=null,repeat:h=0,colorDepth:g=8,dispose:_=-1}=r,v=!1;if(i?u||=(v=!0,d(),!0):v=!!r.first,t=Math.max(0,Math.floor(t)),n=Math.max(0,Math.floor(n)),v){if(!m)throw Error(`First frame must include a { palette } option`);M(a,t,n,m,g),P(a,m),h>=0&&N(a,h)}let y=Math.round(p/10);j(a,_,y,o,f);let b=!!m&&!v;F(a,t,n,b?m:null),b&&P(a,m),I(a,e,t,n,g,s,c,l)}};function d(){R(a,`GIF89a`)}}function j(e,t,n,r,i){e.writeByte(33),e.writeByte(249),e.writeByte(4),i<0&&(i=0,r=!1);var a,o;r?(a=1,o=2):(a=0,o=0),t>=0&&(o=t&7),o<<=2,e.writeByte(o|0|a),L(e,n),e.writeByte(i||0),e.writeByte(0)}function M(e,t,n,r,i=8){let a=z(r.length)-1,o=i-1<<4|128|a;L(e,t),L(e,n),e.writeBytes([o,0,0])}function N(e,t){e.writeByte(33),e.writeByte(255),e.writeByte(11),R(e,`NETSCAPE2.0`),e.writeByte(3),e.writeByte(1),L(e,t),e.writeByte(0)}function P(e,t){let n=1<<z(t.length);for(let r=0;r<n;r++){let n=[0,0,0];r<t.length&&(n=t[r]),e.writeByte(n[0]),e.writeByte(n[1]),e.writeByte(n[2])}}function F(e,t,n,r){if(e.writeByte(44),L(e,0),L(e,0),L(e,t),L(e,n),r){let t=z(r.length)-1;e.writeByte(128|t)}else e.writeByte(0)}function I(e,t,n,r,i=8,a,o,s){c(n,r,t,i,e,a,o,s)}function L(e,t){e.writeByte(t&255),e.writeByte(t>>8&255)}function R(e,t){for(var n=0;n<t.length;n++)e.writeByte(t.charCodeAt(n))}function z(e){return Math.max(Math.ceil(Math.log2(e)),1)}var B=A}))();let t=null,n=!0;self.onmessage=e=>{r(e.data).catch(t=>{e.data?.id!=null&&self.postMessage({id:e.data.id,type:`error`,message:t instanceof Error?t.message:String(t)})})};async function r(r){let a=(e,t=[])=>self.postMessage({id:r.id,...e},t);switch(r.type){case`encode-png`:{let e=r.bitmap,t=new OffscreenCanvas(e.width,e.height),n=t.getContext(`2d`);if(!n)throw Error(`OffscreenCanvas 2d unavailable`);n.drawImage(e,0,0),e.close();let o=await t.convertToBlob({type:`image/png`});o.size>18e5&&(o=await t.convertToBlob({type:`image/jpeg`,quality:.85})),a({type:`png`,dataUrl:await i(o)});return}case`gif-init`:t=(0,e.GIFEncoder)(),n=!0,a({type:`ok`});return;case`gif-frame`:{if(!t)return;let i=new Uint8ClampedArray(r.buffer),a=(0,e.quantize)(i,256,{format:`rgb565`}),o=(0,e.applyPalette)(i,a,`rgb565`);t.writeFrame(o,r.width,r.height,{palette:a,delay:r.delay,first:n,repeat:0}),n=!1;return}case`gif-finish`:{if(!t)throw Error(`No active GIF session`);t.finish();let e=t.bytes();t=null,a({type:`gif`,buffer:e.buffer},[e.buffer]);return}case`gif-abort`:t=null;return}}function i(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>t(r.result),r.onerror=()=>n(r.error),r.readAsDataURL(e)})}})();",DD=typeof self<`u`&&self.Blob&&new Blob([`(self.URL || self.webkitURL).revokeObjectURL(self.location.href);`,ED],{type:`text/javascript;charset=utf-8`});function OD(e){let t;try{if(t=DD&&(self.URL||self.webkitURL).createObjectURL(DD),!t)throw``;let n=new Worker(t,{name:e?.name});return n.addEventListener(`error`,()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),n}catch{return new Worker(`data:text/javascript;charset=utf-8,`+encodeURIComponent(ED),{name:e?.name})}}var kD,AD=1,jD=new Map;function MD(){if(kD!==void 0)return kD;try{kD=new OD,kD.onmessage=e=>{let t=e.data?.id;if(t==null)return;let n=jD.get(t);n&&(jD.delete(t),e.data.type===`error`?n.reject(Error(e.data.message??`Worker error`)):n.resolve(e.data))},kD.onerror=()=>{for(let e of jD.values())e.reject(Error(`Image worker crashed`));jD.clear()}}catch{kD=null}return kD}function ND(e,t=[]){let n=MD();if(!n)return Promise.reject(Error(`Image worker unavailable`));let r=AD++;return new Promise((i,a)=>{jD.set(r,{resolve:i,reject:a}),n.postMessage({...e,id:r},t)})}function PD(e,t=[]){let n=MD();return n?(n.postMessage(e,t),!0):!1}var FD=6,ID=Math.round(1e3/FD),LD=3e4,RD=640,zD={phase:`idle`,startedAt:null,result:null,error:null,attachOnCreate:!0},BD=new Set;function VD(e){zD={...zD,...e};for(let e of BD)e(zD)}function HD(){return zD}function UD(e){return BD.add(e),()=>BD.delete(e)}var WD=null,GD=null,KD=null,qD=null,JD=null,YD=null,XD=!1,ZD=0,QD=!0;async function $D(){if(zD.phase===`recording`||zD.phase===`processing`)return;tO();try{WD=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:FD},audio:!1,preferCurrentTab:!0,selfBrowserSurface:`include`,surfaceSwitching:`exclude`,monitorTypeSurfaces:`exclude`,systemAudio:`exclude`})}catch{VD({phase:`error`,error:`Screen capture was denied or cancelled.`});return}let e=WD.getVideoTracks()[0];if(!e){VD({phase:`error`,error:`No video track available.`}),iO();return}e.addEventListener(`ended`,()=>void eO()),GD=document.createElement(`video`),GD.muted=!0,GD.playsInline=!0,GD.srcObject=WD,await GD.play().catch(()=>{});let t=Date.now()+3e3;for(;!GD.videoWidth&&Date.now()<t;)await new Promise(e=>setTimeout(e,50));if(!GD.videoWidth){VD({phase:`error`,error:`Could not read the capture stream.`}),iO();return}let n=Math.min(1,RD/GD.videoWidth),r=Math.round(GD.videoWidth*n),i=Math.round(GD.videoHeight*n);if(KD=document.createElement(`canvas`),KD.width=r,KD.height=i,qD=KD.getContext(`2d`,{willReadFrequently:!0}),!qD){VD({phase:`error`,error:`Canvas is unavailable.`}),iO();return}XD=await ND({type:`gif-init`}).then(()=>!0,()=>!1),YD=XD?null:(0,TD.GIFEncoder)(),ZD=0,QD=!0,VD({phase:`recording`,startedAt:Date.now(),error:null,result:null}),JD=setInterval(()=>{if(!qD||!GD||!KD)return;let e=zD.startedAt??Date.now();if(Date.now()-e>=LD){eO();return}try{qD.drawImage(GD,0,0,KD.width,KD.height);let{data:e}=qD.getImageData(0,0,KD.width,KD.height);if(XD)PD({type:`gif-frame`,buffer:e.buffer,width:KD.width,height:KD.height,delay:ID},[e.buffer]);else if(YD){let t=(0,TD.quantize)(e,256,{format:`rgb565`}),n=(0,TD.applyPalette)(e,t,`rgb565`);YD.writeFrame(n,KD.width,KD.height,{palette:t,delay:ID,first:QD,repeat:0}),QD=!1}ZD++}catch{}},ID)}async function eO(){if(zD.phase!==`recording`)return;let e=zD.startedAt??Date.now();VD({phase:`processing`}),JD&&=(clearInterval(JD),null);let t=KD?.width??0,n=KD?.height??0,r=ZD,i=YD,a=XD;if(YD=null,XD=!1,iO(),!i&&!a||r===0){VD({phase:`error`,error:`Nothing was captured.`});return}try{let o;if(a){let e=await ND({type:`gif-finish`});o=new Uint8Array(e.buffer)}else i.finish(),o=i.bytes();let s=new Blob([o.buffer],{type:`image/gif`});VD({phase:`ready`,result:{blob:s,url:URL.createObjectURL(s),width:t,height:n,frameCount:r,durationMs:Date.now()-e}})}catch(e){VD({phase:`error`,error:e instanceof Error?e.message:`GIF encoding failed.`})}}function tO(){zD.result?.url&&URL.revokeObjectURL(zD.result.url),iO(),JD&&=(clearInterval(JD),null),XD&&PD({type:`gif-abort`}),XD=!1,YD=null,ZD=0,VD({phase:`idle`,startedAt:null,result:null,error:null,attachOnCreate:!0})}function nO(e){VD({attachOnCreate:e})}function rO(e){zD.result&&VD({result:{...zD.result,assetUrl:e}})}function iO(){WD?.getTracks().forEach(e=>e.stop()),WD=null,GD&&=(GD.srcObject=null,null),KD=null,qD=null}Br();var aO=`https://api.linear.app/graphql`,oO=class extends Error{status;constructor(e,t){super(e),this.status=t,this.name=`LinearError`}},sO=class extends oO{constructor(){super(`Not connected to Linear. Add an API key or connect OAuth in Settings.`),this.name=`LinearNotConnectedError`}};async function cO(e,t){let{linearApiKey:n,linearAccessToken:r}=await Tr(),i=r?`Bearer ${r}`:n;if(!i)throw new sO;let a=await fetch(aO,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:i},body:JSON.stringify({query:e,variables:t})}),o=await a.json().catch(()=>null);if(!a.ok)throw new oO(o?.errors?.[0]?.message??`Linear request failed (${a.status})`,a.status);if(o?.errors?.length)throw new oO(o.errors[0].message);if(!o?.data)throw new oO(`Empty response from Linear`);return o.data}async function lO(){return(await cO(`query { viewer { id name email } }`)).viewer}async function uO(){return(await cO(`query { teams(first: 50) { nodes { id key name } } }`)).teams.nodes}async function dO(){return(await cO(`query {
120
+ of the other sections.`,hD="- FIRST, self-orient in the repo checkout (skip any path that doesn't exist):\n 1. Read `CLAUDE.md` and `AGENTS.md` at the repo root — the master map of product rules, architecture, and memory/skill pointers.\n 2. Skim `.claude/memory/MEMORY.md` (the index) to learn what project memory exists; load the specific `.claude/memory/*.md` files the map names for the surface you're touching.\n 3. Load the matching `.claude/skills/<name>/SKILL.md` files before designing, building UI, or animating (if skills are symlinked, follow them into `.agents/skills/`).\n Treat all of this as authoritative — it overrides your defaults.\n- Live render telemetry (react-scan → linear-grab bridge): if `.lineargrab/scan.ndjson` exists in the repo, it holds the user's REAL interaction slowdowns — component render counts, self-times, change causes (`prop:x`/`state:i`/`context:y`), and interaction latencies, newest last. `curl -s http://127.0.0.1:4577/scan/report` returns an aggregated view. For any re-render/performance issue: read it BEFORE fixing (the evidence) and AFTER (the proof), and cite before→after numbers in your closeout.\n- Keep going until the code works and you're happy with the implementation.\n- MANDATORY COMPLETION GATE — the task is NOT complete (and you may not call it complete) until every step below is done, in order. Skipping any step silently is a FAILED task:\n 1. RUN the app and TEST your change hands-on (computer use / a real browser against the running app). Code reading alone does not count as verification.\n 2. RECORD a demo video or GIF showing the fix working (before → after where possible). If your environment genuinely cannot record media, capture before/after screenshots instead AND state explicitly in your closeout comment why video was not possible — never just omit the demo.\n 3. Open the PR, babysit it for the first set of review comments, and address them. If the repo has preview deployments (e.g. Vercel), wait for the preview to go green and include its URL — deep-linked to the changed page — in the PR body, the Linear closeout, and the announcement.\n 4. CLOSE OUT THE LINEAR ISSUE: post a completion comment (one-line fix summary + PR link), attach the demo media to the ISSUE itself (not only the PR), and move the issue to its review/done state."})),_D=r({describeAiError:()=>bD,executeDraft:()=>vD});async function vD(e,t,n){let r=await jx(e.tier);try{return await yD(r,e,t,n,!1)}catch(i){if(n.aborted)throw i;let a=await Mx(r.provider,e.tier);if(!a)throw Error(bD(i));try{return await yD(a,e,t,n,!0)}catch(e){throw Error(bD(e))}}}async function yD(e,t,n,r,i){let a=bT({model:e.model,schema:sD,system:mD,prompt:dD(t),abortSignal:r});for await(let e of a.partialObjectStream)n(e);return{draft:await a.object,provider:e.provider,modelId:e.modelId,fellBack:i}}function bD(e){let t=e instanceof Error?e.message:String(e);return/401|unauthorized|invalid.*key/i.test(t)?`AI provider rejected the API key.`:/429|rate/i.test(t)?`AI provider rate limit hit — try again shortly.`:`Draft failed: ${t}`}var xD=t((()=>{aD(),cD(),gD(),Fx()}));Sr(),Fx();function SD(e,t){return xr?CD(e,t):wD(e,t)}function CD(e,t){let n=chrome.runtime.connect({name:`ai-draft`}),r=!1;return n.onMessage.addListener(e=>{e.type===`partial`?t.onPartial(e.draft):e.type===`done`?(r=!0,t.onDone(e),n.disconnect()):e.type===`error`&&(r=!0,t.onError(e.message,e.code===`no-provider`?`no-provider`:`unknown`),n.disconnect())}),n.onDisconnect.addListener(()=>{r||t.onError(`Draft stream disconnected.`)}),n.postMessage({type:`start`,input:e}),()=>{try{n.disconnect()}catch{}}}function wD(e,t){let n=new AbortController;return(async()=>{let{executeDraft:r}=await Promise.resolve().then(()=>(xD(),_D));try{let i=await r(e,t.onPartial,n.signal);n.signal.aborted||t.onDone(i)}catch(e){if(n.signal.aborted)return;t.onError(e instanceof Error?e.message:String(e),e instanceof Px?`no-provider`:`unknown`)}})(),()=>n.abort()}var TD=n((e=>{var t=Object.defineProperty;(e=>t(e,`__esModule`,{value:!0}))(e),((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(e,{GIFEncoder:()=>ee,applyPalette:()=>S,default:()=>le,nearestColor:()=>k,nearestColorIndex:()=>D,nearestColorIndexWithDistance:()=>O,prequantize:()=>x,quantize:()=>_,snapColorsToPalette:()=>T});var n={signature:`GIF`,version:`89a`,trailer:59,extensionIntroducer:33,applicationExtensionLabel:255,graphicControlExtensionLabel:249,imageSeparator:44,signatureSize:3,versionSize:3,globalColorTableFlagMask:128,colorResolutionMask:112,sortFlagMask:8,globalColorTableSizeMask:7,applicationIdentifierSize:8,applicationAuthCodeSize:3,disposalMethodMask:28,userInputFlagMask:2,transparentColorFlagMask:1,localColorTableFlagMask:128,interlaceFlagMask:64,idSortFlagMask:32,localColorTableSizeMask:7};function r(e=256){let t=0,n=new Uint8Array(e);return{get buffer(){return n.buffer},reset(){t=0},bytesView(){return n.subarray(0,t)},bytes(){return n.slice(0,t)},writeByte(e){r(t+1),n[t]=e,t++},writeBytes(e,i=0,a=e.length){r(t+a);for(let r=0;r<a;r++)n[t++]=e[r+i]},writeBytesView(e,i=0,a=e.byteLength){r(t+a),n.set(e.subarray(i,i+a),t),t+=a}};function r(e){var r=n.length;if(r>=e)return;e=Math.max(e,r*(r<1024*1024?2:1.125)>>>0),r!=0&&(e=Math.max(e,256));let i=n;n=new Uint8Array(e),t>0&&n.set(i.subarray(0,t),0)}}var i=12,a=5003,o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function s(e,t,n,s,c=r(512),l=new Uint8Array(256),u=new Int32Array(a),d=new Int32Array(a)){let f=u.length,p=Math.max(2,s);l.fill(0),d.fill(0),u.fill(-1);let m=0,h=0,g=p+1,_=g,v=!1,y=_,b=(1<<y)-1,x=1<<g-1,S=x+1,C=x+2,w=0,T=n[0],E=0;for(let e=f;e<65536;e*=2)++E;E=8-E,c.writeByte(p),O(x);let D=n.length;for(let e=1;e<D;e++)next_block:{let t=n[e],r=(t<<i)+T,a=t<<E^T;if(u[a]===r){T=d[a];break next_block}let o=a===0?1:f-a;for(;u[a]>=0;)if(a-=o,a<0&&(a+=f),u[a]===r){T=d[a];break next_block}O(T),T=t,C<1<<i?(d[a]=C++,u[a]=r):(u.fill(-1),C=x+2,v=!0,O(x))}return O(T),O(S),c.writeByte(0),c.bytesView();function O(e){for(m&=o[h],h>0?m|=e<<h:m=e,h+=y;h>=8;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;if((C>b||v)&&(v?(y=_,b=(1<<y)-1,v=!1):(++y,b=y===i?1<<y:(1<<y)-1)),e==S){for(;h>0;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;w>0&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0)}}}var c=s;function l(e,t,n){return e<<8&63488|t<<2&992|n>>3}function u(e,t,n,r){return e>>4|t&240|(n&240)<<4|(r&240)<<8}function d(e,t,n){return e>>4<<8|t&240|n>>4}function f(e,t,n){return e<t?t:e>n?n:e}function p(e){return e*e}function m(e,t,n){var r=0,i=1e100;let a=e[t],o=a.cnt,s=a.ac,c=a.rc,l=a.gc,u=a.bc;for(var d=a.fw;d!=0;d=e[d].fw){let t=e[d],a=t.cnt,m=o*a/(o+a);if(!(m>=i)){var f=0;n&&(f+=m*p(t.ac-s),f>=i)||(f+=m*p(t.rc-c),!(f>=i)&&(f+=m*p(t.gc-l),!(f>=i)&&(f+=m*p(t.bc-u),!(f>=i)&&(i=f,r=d))))}}a.err=i,a.nn=r}function h(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function g(e,t){let n=Array(t===`rgb444`?4096:65536),r=e.length;if(t===`rgba4444`)for(let t=0;t<r;++t){let r=e[t],i=r>>24&255,a=r>>16&255,o=r>>8&255,s=r&255,c=u(s,o,a,i),l=c in n?n[c]:n[c]=h();l.rc+=s,l.gc+=o,l.bc+=a,l.ac+=i,l.cnt++}else if(t===`rgb444`)for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=d(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}else for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=l(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}return n}function _(e,t,n={}){let{format:r=`rgb565`,clearAlpha:i=!0,clearAlphaColor:a=0,clearAlphaThreshold:o=0,oneBitAlpha:s=!1}=n;if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);let c=new Uint32Array(e.buffer),l=n.useSqrt!==!1,u=r===`rgba4444`,d=g(c,r),h=d.length,_=h-1,y=new Uint32Array(h+1);for(var b=0,x=0;x<h;++x){let e=d[x];if(e!=null){var S=1/e.cnt;u&&(e.ac*=S),e.rc*=S,e.gc*=S,e.bc*=S,d[b++]=e}}p(t)/b<.022&&(l=!1);for(var x=0;x<b-1;++x)d[x].fw=x+1,d[x+1].bk=x,l&&(d[x].cnt=Math.sqrt(d[x].cnt));l&&(d[x].cnt=Math.sqrt(d[x].cnt));var C,w,T;for(x=0;x<b;++x){m(d,x,!1);var E=d[x].err;for(w=++y[0];w>1&&(T=w>>1,!(d[C=y[T]].err<=E));w=T)y[w]=C;y[w]=x}var D=b-t;for(x=0;x<D;){for(var O;;){var k=y[1];if(O=d[k],O.tm>=O.mtm&&d[O.nn].mtm<=O.tm)break;O.mtm==_?k=y[1]=y[y[0]--]:(m(d,k,!1),O.tm=x);var E=d[k].err;for(w=1;(T=w+w)<=y[0]&&(T<y[0]&&d[y[T]].err>d[y[T+1]].err&&T++,!(E<=d[C=y[T]].err));w=T)y[w]=C;y[w]=k}var ee=d[O.nn],te=O.cnt,A=ee.cnt,S=1/(te+A);u&&(O.ac=S*(te*O.ac+A*ee.ac)),O.rc=S*(te*O.rc+A*ee.rc),O.gc=S*(te*O.gc+A*ee.gc),O.bc=S*(te*O.bc+A*ee.bc),O.cnt+=ee.cnt,O.mtm=++x,d[ee.bk].fw=ee.fw,d[ee.fw].bk=ee.bk,ee.mtm=_}let ne=[];var re=0;for(x=0;;++re){let e=f(Math.round(d[x].rc),0,255),t=f(Math.round(d[x].gc),0,255),n=f(Math.round(d[x].bc),0,255),r=255;u&&(r=f(Math.round(d[x].ac),0,255),s&&(r=r<=(typeof s==`number`?s:127)?0:255),i&&r<=o&&(e=t=n=a,r=0));let c=u?[e,t,n,r]:[e,t,n];if(v(ne,c)||ne.push(c),(x=d[x].fw)==0)break}return ne}function v(e,t){for(let n=0;n<e.length;n++){let r=e[n],i=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],a=r.length>=4&&t.length>=4?r[3]===t[3]:!0;if(i&&a)return!0}return!1}function y(e,t){var n=0,r;for(r=0;r<e.length;r++){let i=e[r]-t[r];n+=i*i}return n}function b(e,t){return t>1?Math.round(e/t)*t:e}function x(e,{roundRGB:t=5,roundAlpha:n=10,oneBitAlpha:r=null}={}){let i=new Uint32Array(e.buffer);for(let e=0;e<i.length;e++){let a=i[e],o=a>>24&255,s=a>>16&255,c=a>>8&255,l=a&255;o=b(o,n),r&&(o=o<=(typeof r==`number`?r:127)?0:255),l=b(l,t),c=b(c,t),s=b(s,t),i[e]=o<<24|s<<16|c<<8|l<<0}}function S(e,t,n=`rgb565`){if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);if(t.length>256)throw Error(`applyPalette() only works with 256 colors or less`);let r=new Uint32Array(e.buffer),i=r.length,a=n===`rgb444`?4096:65536,o=new Uint8Array(i),s=Array(a);if(n===`rgba4444`)for(let e=0;e<i;e++){let n=r[e],i=n>>24&255,a=n>>16&255,c=n>>8&255,l=n&255,d=u(l,c,a,i);o[e]=d in s?s[d]:s[d]=C(l,c,a,i,t)}else{let e=n===`rgb444`?d:l;for(let n=0;n<i;n++){let i=r[n],a=i>>16&255,c=i>>8&255,l=i&255,u=e(l,c,a);o[n]=u in s?s[u]:s[u]=w(l,c,a,t)}}return o}function C(e,t,n,r,i){let a=0,o=1e100;for(let s=0;s<i.length;s++){let c=i[s],l=c[3],u=E(l-r);if(u>o)continue;let d=c[0];if(u+=E(d-e),u>o)continue;let f=c[1];if(u+=E(f-t),u>o)continue;let p=c[2];u+=E(p-n),!(u>o)&&(o=u,a=s)}return a}function w(e,t,n,r){let i=0,a=1e100;for(let o=0;o<r.length;o++){let s=r[o],c=s[0],l=E(c-e);if(l>a)continue;let u=s[1];if(l+=E(u-t),l>a)continue;let d=s[2];l+=E(d-n),!(l>a)&&(a=l,i=o)}return i}function T(e,t,n=5){if(!e.length||!t.length)return;let r=e.map(e=>e.slice(0,3)),i=n*n,a=e[0].length;for(let n=0;n<t.length;n++){let o=t[n];o=o.length<a?[o[0],o[1],o[2],255]:o.length>a?o.slice(0,3):o.slice();let s=O(r,o.slice(0,3),y),c=s[0],l=s[1];l>0&&l<=i&&(e[c]=o)}}function E(e){return e*e}function D(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return i}function O(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return[i,r]}function k(e,t,n=y){return e[D(e,t,n)]}function ee(e={}){let{initialCapacity:t=4096,auto:i=!0}=e,a=r(t),o=5003,s=new Uint8Array(256),c=new Int32Array(o),l=new Int32Array(o),u=!1;return{reset(){a.reset(),u=!1},finish(){a.writeByte(n.trailer)},bytes(){return a.bytes()},bytesView(){return a.bytesView()},get buffer(){return a.buffer},get stream(){return a},writeHeader:d,writeFrame(e,t,n,r={}){let{transparent:o=!1,transparentIndex:f=0,delay:p=0,palette:m=null,repeat:h=0,colorDepth:g=8,dispose:_=-1}=r,v=!1;if(i?u||=(v=!0,d(),!0):v=!!r.first,t=Math.max(0,Math.floor(t)),n=Math.max(0,Math.floor(n)),v){if(!m)throw Error(`First frame must include a { palette } option`);A(a,t,n,m,g),re(a,m),h>=0&&ne(a,h)}let y=Math.round(p/10);te(a,_,y,o,f);let b=!!m&&!v;ie(a,t,n,b?m:null),b&&re(a,m),ae(a,e,t,n,g,s,c,l)}};function d(){se(a,`GIF89a`)}}function te(e,t,n,r,i){e.writeByte(33),e.writeByte(249),e.writeByte(4),i<0&&(i=0,r=!1);var a,o;r?(a=1,o=2):(a=0,o=0),t>=0&&(o=t&7),o<<=2,e.writeByte(o|0|a),oe(e,n),e.writeByte(i||0),e.writeByte(0)}function A(e,t,n,r,i=8){let a=ce(r.length)-1,o=i-1<<4|128|a;oe(e,t),oe(e,n),e.writeBytes([o,0,0])}function ne(e,t){e.writeByte(33),e.writeByte(255),e.writeByte(11),se(e,`NETSCAPE2.0`),e.writeByte(3),e.writeByte(1),oe(e,t),e.writeByte(0)}function re(e,t){let n=1<<ce(t.length);for(let r=0;r<n;r++){let n=[0,0,0];r<t.length&&(n=t[r]),e.writeByte(n[0]),e.writeByte(n[1]),e.writeByte(n[2])}}function ie(e,t,n,r){if(e.writeByte(44),oe(e,0),oe(e,0),oe(e,t),oe(e,n),r){let t=ce(r.length)-1;e.writeByte(128|t)}else e.writeByte(0)}function ae(e,t,n,r,i=8,a,o,s){c(n,r,t,i,e,a,o,s)}function oe(e,t){e.writeByte(t&255),e.writeByte(t>>8&255)}function se(e,t){for(var n=0;n<t.length;n++)e.writeByte(t.charCodeAt(n))}function ce(e){return Math.max(Math.ceil(Math.log2(e)),1)}var le=ee}))(),ED="(function(){var e=((e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports))((e=>{var t=Object.defineProperty;(e=>t(e,`__esModule`,{value:!0}))(e),((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(e,{GIFEncoder:()=>A,applyPalette:()=>S,default:()=>B,nearestColor:()=>k,nearestColorIndex:()=>D,nearestColorIndexWithDistance:()=>O,prequantize:()=>x,quantize:()=>_,snapColorsToPalette:()=>T});var n={signature:`GIF`,version:`89a`,trailer:59,extensionIntroducer:33,applicationExtensionLabel:255,graphicControlExtensionLabel:249,imageSeparator:44,signatureSize:3,versionSize:3,globalColorTableFlagMask:128,colorResolutionMask:112,sortFlagMask:8,globalColorTableSizeMask:7,applicationIdentifierSize:8,applicationAuthCodeSize:3,disposalMethodMask:28,userInputFlagMask:2,transparentColorFlagMask:1,localColorTableFlagMask:128,interlaceFlagMask:64,idSortFlagMask:32,localColorTableSizeMask:7};function r(e=256){let t=0,n=new Uint8Array(e);return{get buffer(){return n.buffer},reset(){t=0},bytesView(){return n.subarray(0,t)},bytes(){return n.slice(0,t)},writeByte(e){r(t+1),n[t]=e,t++},writeBytes(e,i=0,a=e.length){r(t+a);for(let r=0;r<a;r++)n[t++]=e[r+i]},writeBytesView(e,i=0,a=e.byteLength){r(t+a),n.set(e.subarray(i,i+a),t),t+=a}};function r(e){var r=n.length;if(r>=e)return;e=Math.max(e,r*(r<1024*1024?2:1.125)>>>0),r!=0&&(e=Math.max(e,256));let i=n;n=new Uint8Array(e),t>0&&n.set(i.subarray(0,t),0)}}var i=12,a=5003,o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function s(e,t,n,s,c=r(512),l=new Uint8Array(256),u=new Int32Array(a),d=new Int32Array(a)){let f=u.length,p=Math.max(2,s);l.fill(0),d.fill(0),u.fill(-1);let m=0,h=0,g=p+1,_=g,v=!1,y=_,b=(1<<y)-1,x=1<<g-1,S=x+1,C=x+2,w=0,T=n[0],E=0;for(let e=f;e<65536;e*=2)++E;E=8-E,c.writeByte(p),O(x);let D=n.length;for(let e=1;e<D;e++)next_block:{let t=n[e],r=(t<<i)+T,a=t<<E^T;if(u[a]===r){T=d[a];break next_block}let o=a===0?1:f-a;for(;u[a]>=0;)if(a-=o,a<0&&(a+=f),u[a]===r){T=d[a];break next_block}O(T),T=t,C<1<<i?(d[a]=C++,u[a]=r):(u.fill(-1),C=x+2,v=!0,O(x))}return O(T),O(S),c.writeByte(0),c.bytesView();function O(e){for(m&=o[h],h>0?m|=e<<h:m=e,h+=y;h>=8;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;if((C>b||v)&&(v?(y=_,b=(1<<y)-1,v=!1):(++y,b=y===i?1<<y:(1<<y)-1)),e==S){for(;h>0;)l[w++]=m&255,w>=254&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0),m>>=8,h-=8;w>0&&(c.writeByte(w),c.writeBytesView(l,0,w),w=0)}}}var c=s;function l(e,t,n){return e<<8&63488|t<<2&992|n>>3}function u(e,t,n,r){return e>>4|t&240|(n&240)<<4|(r&240)<<8}function d(e,t,n){return e>>4<<8|t&240|n>>4}function f(e,t,n){return e<t?t:e>n?n:e}function p(e){return e*e}function m(e,t,n){var r=0,i=1e100;let a=e[t],o=a.cnt,s=a.ac,c=a.rc,l=a.gc,u=a.bc;for(var d=a.fw;d!=0;d=e[d].fw){let t=e[d],a=t.cnt,m=o*a/(o+a);if(!(m>=i)){var f=0;n&&(f+=m*p(t.ac-s),f>=i)||(f+=m*p(t.rc-c),!(f>=i)&&(f+=m*p(t.gc-l),!(f>=i)&&(f+=m*p(t.bc-u),!(f>=i)&&(i=f,r=d))))}}a.err=i,a.nn=r}function h(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function g(e,t){let n=Array(t===`rgb444`?4096:65536),r=e.length;if(t===`rgba4444`)for(let t=0;t<r;++t){let r=e[t],i=r>>24&255,a=r>>16&255,o=r>>8&255,s=r&255,c=u(s,o,a,i),l=c in n?n[c]:n[c]=h();l.rc+=s,l.gc+=o,l.bc+=a,l.ac+=i,l.cnt++}else if(t===`rgb444`)for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=d(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}else for(let t=0;t<r;++t){let r=e[t],i=r>>16&255,a=r>>8&255,o=r&255,s=l(o,a,i),c=s in n?n[s]:n[s]=h();c.rc+=o,c.gc+=a,c.bc+=i,c.cnt++}return n}function _(e,t,n={}){let{format:r=`rgb565`,clearAlpha:i=!0,clearAlphaColor:a=0,clearAlphaThreshold:o=0,oneBitAlpha:s=!1}=n;if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);let c=new Uint32Array(e.buffer),l=n.useSqrt!==!1,u=r===`rgba4444`,d=g(c,r),h=d.length,_=h-1,y=new Uint32Array(h+1);for(var b=0,x=0;x<h;++x){let e=d[x];if(e!=null){var S=1/e.cnt;u&&(e.ac*=S),e.rc*=S,e.gc*=S,e.bc*=S,d[b++]=e}}p(t)/b<.022&&(l=!1);for(var x=0;x<b-1;++x)d[x].fw=x+1,d[x+1].bk=x,l&&(d[x].cnt=Math.sqrt(d[x].cnt));l&&(d[x].cnt=Math.sqrt(d[x].cnt));var C,w,T;for(x=0;x<b;++x){m(d,x,!1);var E=d[x].err;for(w=++y[0];w>1&&(T=w>>1,!(d[C=y[T]].err<=E));w=T)y[w]=C;y[w]=x}var D=b-t;for(x=0;x<D;){for(var O;;){var k=y[1];if(O=d[k],O.tm>=O.mtm&&d[O.nn].mtm<=O.tm)break;O.mtm==_?k=y[1]=y[y[0]--]:(m(d,k,!1),O.tm=x);var E=d[k].err;for(w=1;(T=w+w)<=y[0]&&(T<y[0]&&d[y[T]].err>d[y[T+1]].err&&T++,!(E<=d[C=y[T]].err));w=T)y[w]=C;y[w]=k}var A=d[O.nn],j=O.cnt,M=A.cnt,S=1/(j+M);u&&(O.ac=S*(j*O.ac+M*A.ac)),O.rc=S*(j*O.rc+M*A.rc),O.gc=S*(j*O.gc+M*A.gc),O.bc=S*(j*O.bc+M*A.bc),O.cnt+=A.cnt,O.mtm=++x,d[A.bk].fw=A.fw,d[A.fw].bk=A.bk,A.mtm=_}let N=[];var P=0;for(x=0;;++P){let e=f(Math.round(d[x].rc),0,255),t=f(Math.round(d[x].gc),0,255),n=f(Math.round(d[x].bc),0,255),r=255;u&&(r=f(Math.round(d[x].ac),0,255),s&&(r=r<=(typeof s==`number`?s:127)?0:255),i&&r<=o&&(e=t=n=a,r=0));let c=u?[e,t,n,r]:[e,t,n];if(v(N,c)||N.push(c),(x=d[x].fw)==0)break}return N}function v(e,t){for(let n=0;n<e.length;n++){let r=e[n],i=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],a=r.length>=4&&t.length>=4?r[3]===t[3]:!0;if(i&&a)return!0}return!1}function y(e,t){var n=0,r;for(r=0;r<e.length;r++){let i=e[r]-t[r];n+=i*i}return n}function b(e,t){return t>1?Math.round(e/t)*t:e}function x(e,{roundRGB:t=5,roundAlpha:n=10,oneBitAlpha:r=null}={}){let i=new Uint32Array(e.buffer);for(let e=0;e<i.length;e++){let a=i[e],o=a>>24&255,s=a>>16&255,c=a>>8&255,l=a&255;o=b(o,n),r&&(o=o<=(typeof r==`number`?r:127)?0:255),l=b(l,t),c=b(c,t),s=b(s,t),i[e]=o<<24|s<<16|c<<8|l<<0}}function S(e,t,n=`rgb565`){if(!e||!e.buffer||!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw Error(`quantize() expected RGBA Uint8Array data`);if(t.length>256)throw Error(`applyPalette() only works with 256 colors or less`);let r=new Uint32Array(e.buffer),i=r.length,a=n===`rgb444`?4096:65536,o=new Uint8Array(i),s=Array(a);if(n===`rgba4444`)for(let e=0;e<i;e++){let n=r[e],i=n>>24&255,a=n>>16&255,c=n>>8&255,l=n&255,d=u(l,c,a,i);o[e]=d in s?s[d]:s[d]=C(l,c,a,i,t)}else{let e=n===`rgb444`?d:l;for(let n=0;n<i;n++){let i=r[n],a=i>>16&255,c=i>>8&255,l=i&255,u=e(l,c,a);o[n]=u in s?s[u]:s[u]=w(l,c,a,t)}}return o}function C(e,t,n,r,i){let a=0,o=1e100;for(let s=0;s<i.length;s++){let c=i[s],l=c[3],u=E(l-r);if(u>o)continue;let d=c[0];if(u+=E(d-e),u>o)continue;let f=c[1];if(u+=E(f-t),u>o)continue;let p=c[2];u+=E(p-n),!(u>o)&&(o=u,a=s)}return a}function w(e,t,n,r){let i=0,a=1e100;for(let o=0;o<r.length;o++){let s=r[o],c=s[0],l=E(c-e);if(l>a)continue;let u=s[1];if(l+=E(u-t),l>a)continue;let d=s[2];l+=E(d-n),!(l>a)&&(a=l,i=o)}return i}function T(e,t,n=5){if(!e.length||!t.length)return;let r=e.map(e=>e.slice(0,3)),i=n*n,a=e[0].length;for(let n=0;n<t.length;n++){let o=t[n];o=o.length<a?[o[0],o[1],o[2],255]:o.length>a?o.slice(0,3):o.slice();let s=O(r,o.slice(0,3),y),c=s[0],l=s[1];l>0&&l<=i&&(e[c]=o)}}function E(e){return e*e}function D(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return i}function O(e,t,n=y){let r=1/0,i=-1;for(let a=0;a<e.length;a++){let o=e[a],s=n(t,o);s<r&&(r=s,i=a)}return[i,r]}function k(e,t,n=y){return e[D(e,t,n)]}function A(e={}){let{initialCapacity:t=4096,auto:i=!0}=e,a=r(t),o=5003,s=new Uint8Array(256),c=new Int32Array(o),l=new Int32Array(o),u=!1;return{reset(){a.reset(),u=!1},finish(){a.writeByte(n.trailer)},bytes(){return a.bytes()},bytesView(){return a.bytesView()},get buffer(){return a.buffer},get stream(){return a},writeHeader:d,writeFrame(e,t,n,r={}){let{transparent:o=!1,transparentIndex:f=0,delay:p=0,palette:m=null,repeat:h=0,colorDepth:g=8,dispose:_=-1}=r,v=!1;if(i?u||=(v=!0,d(),!0):v=!!r.first,t=Math.max(0,Math.floor(t)),n=Math.max(0,Math.floor(n)),v){if(!m)throw Error(`First frame must include a { palette } option`);M(a,t,n,m,g),P(a,m),h>=0&&N(a,h)}let y=Math.round(p/10);j(a,_,y,o,f);let b=!!m&&!v;F(a,t,n,b?m:null),b&&P(a,m),I(a,e,t,n,g,s,c,l)}};function d(){R(a,`GIF89a`)}}function j(e,t,n,r,i){e.writeByte(33),e.writeByte(249),e.writeByte(4),i<0&&(i=0,r=!1);var a,o;r?(a=1,o=2):(a=0,o=0),t>=0&&(o=t&7),o<<=2,e.writeByte(o|0|a),L(e,n),e.writeByte(i||0),e.writeByte(0)}function M(e,t,n,r,i=8){let a=z(r.length)-1,o=i-1<<4|128|a;L(e,t),L(e,n),e.writeBytes([o,0,0])}function N(e,t){e.writeByte(33),e.writeByte(255),e.writeByte(11),R(e,`NETSCAPE2.0`),e.writeByte(3),e.writeByte(1),L(e,t),e.writeByte(0)}function P(e,t){let n=1<<z(t.length);for(let r=0;r<n;r++){let n=[0,0,0];r<t.length&&(n=t[r]),e.writeByte(n[0]),e.writeByte(n[1]),e.writeByte(n[2])}}function F(e,t,n,r){if(e.writeByte(44),L(e,0),L(e,0),L(e,t),L(e,n),r){let t=z(r.length)-1;e.writeByte(128|t)}else e.writeByte(0)}function I(e,t,n,r,i=8,a,o,s){c(n,r,t,i,e,a,o,s)}function L(e,t){e.writeByte(t&255),e.writeByte(t>>8&255)}function R(e,t){for(var n=0;n<t.length;n++)e.writeByte(t.charCodeAt(n))}function z(e){return Math.max(Math.ceil(Math.log2(e)),1)}var B=A}))();let t=null,n=!0;self.onmessage=e=>{r(e.data).catch(t=>{e.data?.id!=null&&self.postMessage({id:e.data.id,type:`error`,message:t instanceof Error?t.message:String(t)})})};async function r(r){let a=(e,t=[])=>self.postMessage({id:r.id,...e},t);switch(r.type){case`encode-png`:{let e=r.bitmap,t=new OffscreenCanvas(e.width,e.height),n=t.getContext(`2d`);if(!n)throw Error(`OffscreenCanvas 2d unavailable`);n.drawImage(e,0,0),e.close();let o=await t.convertToBlob({type:`image/png`});o.size>18e5&&(o=await t.convertToBlob({type:`image/jpeg`,quality:.85})),a({type:`png`,dataUrl:await i(o)});return}case`gif-init`:t=(0,e.GIFEncoder)(),n=!0,a({type:`ok`});return;case`gif-frame`:{if(!t)return;let i=new Uint8ClampedArray(r.buffer),a=(0,e.quantize)(i,256,{format:`rgb565`}),o=(0,e.applyPalette)(i,a,`rgb565`);t.writeFrame(o,r.width,r.height,{palette:a,delay:r.delay,first:n,repeat:0}),n=!1;return}case`gif-finish`:{if(!t)throw Error(`No active GIF session`);t.finish();let e=t.bytes();t=null,a({type:`gif`,buffer:e.buffer},[e.buffer]);return}case`gif-abort`:t=null;return}}function i(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>t(r.result),r.onerror=()=>n(r.error),r.readAsDataURL(e)})}})();",DD=typeof self<`u`&&self.Blob&&new Blob([`(self.URL || self.webkitURL).revokeObjectURL(self.location.href);`,ED],{type:`text/javascript;charset=utf-8`});function OD(e){let t;try{if(t=DD&&(self.URL||self.webkitURL).createObjectURL(DD),!t)throw``;let n=new Worker(t,{name:e?.name});return n.addEventListener(`error`,()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),n}catch{return new Worker(`data:text/javascript;charset=utf-8,`+encodeURIComponent(ED),{name:e?.name})}}var kD,AD=1,jD=new Map;function MD(){if(kD!==void 0)return kD;try{kD=new OD,kD.onmessage=e=>{let t=e.data?.id;if(t==null)return;let n=jD.get(t);n&&(jD.delete(t),e.data.type===`error`?n.reject(Error(e.data.message??`Worker error`)):n.resolve(e.data))},kD.onerror=()=>{for(let e of jD.values())e.reject(Error(`Image worker crashed`));jD.clear()}}catch{kD=null}return kD}function ND(e,t=[]){let n=MD();if(!n)return Promise.reject(Error(`Image worker unavailable`));let r=AD++;return new Promise((i,a)=>{jD.set(r,{resolve:i,reject:a}),n.postMessage({...e,id:r},t)})}function PD(e,t=[]){let n=MD();return n?(n.postMessage(e,t),!0):!1}var FD=6,ID=Math.round(1e3/FD),LD=3e4,RD=640,zD={phase:`idle`,startedAt:null,result:null,error:null,attachOnCreate:!0},BD=new Set;function VD(e){zD={...zD,...e};for(let e of BD)e(zD)}function HD(){return zD}function UD(e){return BD.add(e),()=>BD.delete(e)}var WD=null,GD=null,KD=null,qD=null,JD=null,YD=null,XD=!1,ZD=0,QD=!0;async function $D(){if(zD.phase===`recording`||zD.phase===`processing`)return;tO();try{WD=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:FD},audio:!1,preferCurrentTab:!0,selfBrowserSurface:`include`,surfaceSwitching:`exclude`,monitorTypeSurfaces:`exclude`,systemAudio:`exclude`})}catch{VD({phase:`error`,error:`Screen capture was denied or cancelled.`});return}let e=WD.getVideoTracks()[0];if(!e){VD({phase:`error`,error:`No video track available.`}),iO();return}e.addEventListener(`ended`,()=>void eO()),GD=document.createElement(`video`),GD.muted=!0,GD.playsInline=!0,GD.srcObject=WD,await GD.play().catch(()=>{});let t=Date.now()+3e3;for(;!GD.videoWidth&&Date.now()<t;)await new Promise(e=>setTimeout(e,50));if(!GD.videoWidth){VD({phase:`error`,error:`Could not read the capture stream.`}),iO();return}let n=Math.min(1,RD/GD.videoWidth),r=Math.round(GD.videoWidth*n),i=Math.round(GD.videoHeight*n);if(KD=document.createElement(`canvas`),KD.width=r,KD.height=i,qD=KD.getContext(`2d`,{willReadFrequently:!0}),!qD){VD({phase:`error`,error:`Canvas is unavailable.`}),iO();return}XD=await ND({type:`gif-init`}).then(()=>!0,()=>!1),YD=XD?null:(0,TD.GIFEncoder)(),ZD=0,QD=!0,VD({phase:`recording`,startedAt:Date.now(),error:null,result:null}),JD=setInterval(()=>{if(!qD||!GD||!KD)return;let e=zD.startedAt??Date.now();if(Date.now()-e>=LD){eO();return}try{qD.drawImage(GD,0,0,KD.width,KD.height);let{data:e}=qD.getImageData(0,0,KD.width,KD.height);if(XD)PD({type:`gif-frame`,buffer:e.buffer,width:KD.width,height:KD.height,delay:ID},[e.buffer]);else if(YD){let t=(0,TD.quantize)(e,256,{format:`rgb565`}),n=(0,TD.applyPalette)(e,t,`rgb565`);YD.writeFrame(n,KD.width,KD.height,{palette:t,delay:ID,first:QD,repeat:0}),QD=!1}ZD++}catch{}},ID)}async function eO(){if(zD.phase!==`recording`)return;let e=zD.startedAt??Date.now();VD({phase:`processing`}),JD&&=(clearInterval(JD),null);let t=KD?.width??0,n=KD?.height??0,r=ZD,i=YD,a=XD;if(YD=null,XD=!1,iO(),!i&&!a||r===0){VD({phase:`error`,error:`Nothing was captured.`});return}try{let o;if(a){let e=await ND({type:`gif-finish`});o=new Uint8Array(e.buffer)}else i.finish(),o=i.bytes();let s=new Blob([o.buffer],{type:`image/gif`});VD({phase:`ready`,result:{blob:s,url:URL.createObjectURL(s),width:t,height:n,frameCount:r,durationMs:Date.now()-e}})}catch(e){VD({phase:`error`,error:e instanceof Error?e.message:`GIF encoding failed.`})}}function tO(){zD.result?.url&&URL.revokeObjectURL(zD.result.url),iO(),JD&&=(clearInterval(JD),null),XD&&PD({type:`gif-abort`}),XD=!1,YD=null,ZD=0,VD({phase:`idle`,startedAt:null,result:null,error:null,attachOnCreate:!0})}function nO(e){VD({attachOnCreate:e})}function rO(e){zD.result&&VD({result:{...zD.result,assetUrl:e}})}function iO(){WD?.getTracks().forEach(e=>e.stop()),WD=null,GD&&=(GD.srcObject=null,null),KD=null,qD=null}Br();var aO=`https://api.linear.app/graphql`,oO=class extends Error{status;constructor(e,t){super(e),this.status=t,this.name=`LinearError`}},sO=class extends oO{constructor(){super(`Not connected to Linear. Add an API key or connect OAuth in Settings.`),this.name=`LinearNotConnectedError`}};async function cO(e,t){let{linearApiKey:n,linearAccessToken:r}=await Tr(),i=r?`Bearer ${r}`:n;if(!i)throw new sO;let a=await fetch(aO,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:i},body:JSON.stringify({query:e,variables:t})}),o=await a.json().catch(()=>null);if(!a.ok)throw new oO(o?.errors?.[0]?.message??`Linear request failed (${a.status})`,a.status);if(o?.errors?.length)throw new oO(o.errors[0].message);if(!o?.data)throw new oO(`Empty response from Linear`);return o.data}async function lO(){return(await cO(`query { viewer { id name email } }`)).viewer}async function uO(){return(await cO(`query { teams(first: 50) { nodes { id key name } } }`)).teams.nodes}async function dO(){return(await cO(`query {
121
121
  users(filter: { app: { eq: true } }) {
122
122
  nodes { id name displayName url active }
123
123
  }
@@ -25754,7 +25754,7 @@ function pD(e) {
25754
25754
  return i.length && t.push(i.join(" ")), t.join("\n\n");
25755
25755
  }
25756
25756
  var mD, hD, gD = t((() => {
25757
- mD = "You are an expert engineer drafting a Linear issue for a development team.\nYou are given a rough note from the reporter and, when available, the exact React source\nlocation of the UI element the issue is about (captured from a running dev build).\n\nWrite a crisp, actionable issue a coding agent can execute against with zero follow-up\nquestions. Be specific, never invent details you were not given, and keep the tone neutral\nand technical. If the note implies a bug, structure it as a bug; if it implies a change or\nfeature, keep reproSteps minimal and focus the description on the desired change.\n\nThe issue renders in this exact section order — fill each field for its section:\nSummary (description field) → Steps to Reproduce (reproSteps) → Expected Behavior\n(expected) → Actual Behavior (actual) → Impact (impact) → Analysis / Notes\n(analysisNotes, markdown bullets grounded in the provided source context) →\nSuggested Next Steps (suggestedNextSteps, markdown bullets with concrete fixes).\nThe Summary is a short plain-prose paragraph — no headings inside it, no repetition\nof the other sections.", hD = "- FIRST, self-orient in the repo checkout (skip any path that doesn't exist):\n 1. Read `CLAUDE.md` and `AGENTS.md` at the repo root — the master map of product rules, architecture, and memory/skill pointers.\n 2. Skim `.claude/memory/MEMORY.md` (the index) to learn what project memory exists; load the specific `.claude/memory/*.md` files the map names for the surface you're touching.\n 3. Load the matching `.claude/skills/<name>/SKILL.md` files before designing, building UI, or animating (if skills are symlinked, follow them into `.agents/skills/`).\n Treat all of this as authoritative — it overrides your defaults.\n- Keep going until the code works and you're happy with the implementation.\n- MANDATORY COMPLETION GATE — the task is NOT complete (and you may not call it complete) until every step below is done, in order. Skipping any step silently is a FAILED task:\n 1. RUN the app and TEST your change hands-on (computer use / a real browser against the running app). Code reading alone does not count as verification.\n 2. RECORD a demo video or GIF showing the fix working (before → after where possible). If your environment genuinely cannot record media, capture before/after screenshots instead AND state explicitly in your closeout comment why video was not possible — never just omit the demo.\n 3. Open the PR, babysit it for the first set of review comments, and address them. If the repo has preview deployments (e.g. Vercel), wait for the preview to go green and include its URL — deep-linked to the changed page — in the PR body, the Linear closeout, and the announcement.\n 4. CLOSE OUT THE LINEAR ISSUE: post a completion comment (one-line fix summary + PR link), attach the demo media to the ISSUE itself (not only the PR), and move the issue to its review/done state.";
25757
+ mD = "You are an expert engineer drafting a Linear issue for a development team.\nYou are given a rough note from the reporter and, when available, the exact React source\nlocation of the UI element the issue is about (captured from a running dev build).\n\nWrite a crisp, actionable issue a coding agent can execute against with zero follow-up\nquestions. Be specific, never invent details you were not given, and keep the tone neutral\nand technical. If the note implies a bug, structure it as a bug; if it implies a change or\nfeature, keep reproSteps minimal and focus the description on the desired change.\n\nThe issue renders in this exact section order — fill each field for its section:\nSummary (description field) → Steps to Reproduce (reproSteps) → Expected Behavior\n(expected) → Actual Behavior (actual) → Impact (impact) → Analysis / Notes\n(analysisNotes, markdown bullets grounded in the provided source context) →\nSuggested Next Steps (suggestedNextSteps, markdown bullets with concrete fixes).\nThe Summary is a short plain-prose paragraph — no headings inside it, no repetition\nof the other sections.", hD = "- FIRST, self-orient in the repo checkout (skip any path that doesn't exist):\n 1. Read `CLAUDE.md` and `AGENTS.md` at the repo root — the master map of product rules, architecture, and memory/skill pointers.\n 2. Skim `.claude/memory/MEMORY.md` (the index) to learn what project memory exists; load the specific `.claude/memory/*.md` files the map names for the surface you're touching.\n 3. Load the matching `.claude/skills/<name>/SKILL.md` files before designing, building UI, or animating (if skills are symlinked, follow them into `.agents/skills/`).\n Treat all of this as authoritative — it overrides your defaults.\n- Live render telemetry (react-scan → linear-grab bridge): if `.lineargrab/scan.ndjson` exists in the repo, it holds the user's REAL interaction slowdowns — component render counts, self-times, change causes (`prop:x`/`state:i`/`context:y`), and interaction latencies, newest last. `curl -s http://127.0.0.1:4577/scan/report` returns an aggregated view. For any re-render/performance issue: read it BEFORE fixing (the evidence) and AFTER (the proof), and cite before→after numbers in your closeout.\n- Keep going until the code works and you're happy with the implementation.\n- MANDATORY COMPLETION GATE — the task is NOT complete (and you may not call it complete) until every step below is done, in order. Skipping any step silently is a FAILED task:\n 1. RUN the app and TEST your change hands-on (computer use / a real browser against the running app). Code reading alone does not count as verification.\n 2. RECORD a demo video or GIF showing the fix working (before → after where possible). If your environment genuinely cannot record media, capture before/after screenshots instead AND state explicitly in your closeout comment why video was not possible — never just omit the demo.\n 3. Open the PR, babysit it for the first set of review comments, and address them. If the repo has preview deployments (e.g. Vercel), wait for the preview to go green and include its URL — deep-linked to the changed page — in the PR body, the Linear closeout, and the announcement.\n 4. CLOSE OUT THE LINEAR ISSUE: post a completion comment (one-line fix summary + PR link), attach the demo media to the ISSUE itself (not only the PR), and move the issue to its review/done state.";
25758
25758
  })), _D = /* @__PURE__ */ r({
25759
25759
  describeAiError: () => bD,
25760
25760
  executeDraft: () => vD
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linear-grab",
3
- "version": "0.20.1",
3
+ "version": "0.20.2",
4
4
  "type": "module",
5
5
  "description": "Point at any React element in your dev app, draft a Linear issue with AI, delegate it to the Cursor agent, and track it live — in any browser.",
6
6
  "exports": {