@specship/specship-win32-arm64 0.14.2 → 0.14.3

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.
@@ -48,4 +48,4 @@ ${p.calls} calls · ${U(p.tokens)} result tokens · ${U(Math.round(p.tpc))}/call
48
48
  `),t);if(!n)return null;const{title:s,headingLevel:l,statement:o,criteria:a}=n;return{title:s,headingLevel:l,statement:o,criteria:a}}function Ig(e){return{title:e.title.trim(),statement:e.statement.trim(),criteria:e.criteria.map(t=>({text:t.text.trim()})).filter(t=>t.text.length>0)}}function Ag(e,t,n){const s=e.split(`
49
49
  `),l=Lp(s,t);if(!l)return null;const o=[s[l.start],"#".repeat(l.headingLevel)+" "+n.title,""];return n.statement&&o.push(...n.statement.split(`
50
50
  `),""),l.middle.length&&o.push(...l.middle,""),n.criteria.length&&(o.push(l.acceptanceHeading??"## Acceptance"),n.criteria.forEach((a,i)=>{o.push(`<!-- id: ${t}.A${i+1} -->`,`- ${a.text}`)}),o.push("")),[...s.slice(0,l.start),...o,...s.slice(l.end)].join(`
51
- `)}function Rs(e){let t=String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");return t=t.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),t=t.replace(/`([^`]+?)`/g,"<code class='sp-code'>$1</code>"),t=t.replace(/\b(MUST NOT|MUST|SHALL NOT|SHALL|REQUIRED)\b/g,"<span class='sp-kw sp-kw-must'>$1</span>"),t=t.replace(/\b(SHOULD NOT|SHOULD|RECOMMENDED)\b/g,"<span class='sp-kw sp-kw-should'>$1</span>"),t=t.replace(/\b(MAY|OPTIONAL)\b/g,"<span class='sp-kw sp-kw-may'>$1</span>"),t}const Bg=new Set(["verified","implemented","completed"]);function sl(e,t){if(!e||!e.length)return t;const n=e.map(s=>s.state);return n.includes("broken")?"broken":n.includes("orphaned")?"orphaned":n.includes("drifted")?"drifted":n.every(s=>s==="verified")?"verified":"implemented"}const Wg={verified:"check",implemented:"check",completed:"check",drifted:"drift",broken:"cancel",orphaned:"cancel",failed:"cancel"};function $g({state:e}){const t=fe[e]??fe.info,n=Wg[e];return r.jsx("div",{className:"sp-crit-mark",style:{background:t.bg,color:t.color},children:n?r.jsx(z,{name:n,size:12}):r.jsx("span",{style:{width:7,height:7,borderRadius:"50%",border:"1.6px solid "+t.color,boxSizing:"border-box"}})})}function Fc(e){const t=e.lastIndexOf(".");return t===-1?e:e.slice(t+1)}function Fg(e){return fe[e]?.label??e}function Hg({id:e,project:t,cache:n}){return e?r.jsx(Vg,{id:e,project:t,cache:n}):r.jsx(Ug,{})}function Ug(){return r.jsx(ue,{icon:"book",title:"Pick a spec from the tree",body:"Or run specship init -i to index your specs/ folder if you haven’t yet.",action:r.jsxs("span",{className:"row gap-6",style:{justifyContent:"center"},children:[r.jsx("code",{className:"mono",style:{fontSize:11.5,color:"var(--accent)",background:"var(--bg-canvas)",padding:"5px 10px",borderRadius:6,border:"1px solid var(--border-subtle)"},children:"specship init -i"}),r.jsx(pt,{text:"specship init -i"})]})})}function Vg({id:e,project:t,cache:n}){const s=(t??"")+"|"+e,l=L(async()=>{const u=await P.spec(e,t);return n?.set(s,u),u},[e,t]),o=l.data??n?.get(s)??null,[a,i]=N.useState(!1),[c,d]=N.useState(null);return N.useEffect(()=>{i(!1),d(null)},[e]),o?a?r.jsx(rv,{data:o,project:t,onCancel:()=>i(!1),onSaved:u=>{i(!1),d(u),l.reload()}}):r.jsx(Qg,{data:o,notice:c,onEdit:()=>{d(null),i(!0)}}):l.loading?r.jsx(Kg,{}):Kt(l.error)?r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."}):r.jsx(ue,{icon:"drift",title:`Couldn’t load ${e}`,body:l.error instanceof Error?l.error.message:"The spec detail request failed.",action:r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:l.reload,children:[r.jsx(z,{name:"refresh",size:13}),"Retry"]})})}function Kg(){return r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"28px 32px 56px"},"data-testid":"spec-skeleton",children:r.jsxs("div",{className:"sp-doc",children:[r.jsx("div",{className:"skel",style:{width:230,height:12,marginBottom:20}}),r.jsx("div",{className:"skel",style:{width:"72%",height:28,marginBottom:16}}),r.jsx("div",{className:"skel",style:{width:340,height:20,marginBottom:32}}),r.jsx("div",{className:"skel",style:{width:"100%",height:96,marginBottom:30}}),r.jsx("div",{className:"skel",style:{width:"100%",height:132,marginBottom:30}}),r.jsx("div",{className:"skel",style:{width:"100%",height:56}})]})})}function Qg({data:e,notice:t,onEdit:n}){const{spec:s,parent:l,children:o,links:a,childLinks:i}=e,c=l?.sourcePath??s.sourcePath??"",d=e.source!=null&&Dp(e.source,s.id)!=null,u=d?"Edit this requirement in place":e.source==null?"Source file not available":"Couldn’t locate this requirement’s section in the source file",f=o.filter(k=>k.kind==="acceptance"),h=k=>sl(i[k.id],"pending"),g=sl(a,"drafted"),v=f.filter(k=>Bg.has(h(k))).length,p=(fe[g]??fe.info).color,j=g==="verified"?Dr(a.reduce((k,C)=>Math.max(k,C.updatedAt??0),0)||void 0):null,m=g==="verified"?"var(--success)":g==="broken"||g==="drifted"||g==="orphaned"?"var(--warn)":"var(--text-secondary)",x=typeof s.metadata?.rationale=="string"?s.metadata.rationale:typeof s.rationale=="string"?s.rationale:null,y=k=>[k.targetFilePath,k.targetQualifiedName].filter(Boolean).join(":")||"—",w=k=>B("graph",{query:{focus:k.resolvedNodeId||"spec:"+s.id}}),S=r.jsx("span",{className:"sep"});return r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"28px 32px 56px"},children:r.jsxs("div",{className:"sp-doc",children:[t!=null&&r.jsxs("div",{className:"card card-pad row gap-8",style:{color:"var(--warn)",borderColor:"var(--warn)",marginBottom:20,fontSize:12.5},children:[r.jsx(z,{name:"drift",size:14,style:{flexShrink:0}}),r.jsxs("span",{children:["Saved, but not yet indexed — re-sync failed (",t,"). The file is on disk; the next sync picks it up."]})]}),r.jsxs("div",{className:"sp-breadcrumb",children:[r.jsx(z,{name:"book",size:13,style:{color:"var(--node-spec)",flexShrink:0}}),r.jsx("span",{className:"mono sp-path",style:{color:"var(--text-secondary)"},children:c}),r.jsx(z,{name:"chevronRight",size:11,style:{flexShrink:0}}),r.jsx("span",{className:"mono",style:{color:"var(--node-spec)",fontWeight:600,flexShrink:0},children:s.id}),r.jsx(pt,{text:s.id,ariaLabel:"Copy spec id"})]}),r.jsx("h1",{className:"sp-title",children:s.title}),r.jsxs("div",{className:"sp-metaline",style:{marginBottom:32},children:[r.jsx(Ge,{state:g,pulse:g==="broken"||g==="drifted"}),r.jsx(re,{children:s.priority||"—"}),S,r.jsx("span",{className:"fact",children:r.jsx("b",{children:s.kind||"requirement"})}),S,r.jsxs("span",{className:"fact",children:["owned by ",r.jsx("b",{className:"mono",children:s.owner||"—"})]}),S,r.jsxs("span",{className:"fact",children:[g==="verified"?"verified ":null,r.jsx("b",{style:{color:m},children:j?j+" ago":"—"})]})]}),r.jsxs("div",{className:"sp-sec",children:[r.jsx("div",{className:"sp-label",children:"Requirement"}),r.jsx("div",{className:"sp-statement lead",style:{"--sp-accent":p},children:s.body?.trim()?r.jsx("div",{className:"sp-prose",dangerouslySetInnerHTML:{__html:Rs(s.body)}}):r.jsx("div",{className:"muted",style:{fontSize:13},children:"No normative statement recorded."})})]}),x&&r.jsxs("div",{className:"sp-sec",children:[r.jsx("div",{className:"sp-label",children:"Why it matters"}),r.jsx("div",{className:"sp-rationale",dangerouslySetInnerHTML:{__html:Rs(x)}})]}),f.length>0&&r.jsxs("div",{className:"sp-sec",children:[r.jsxs("div",{className:"sp-label",children:["Acceptance criteria",r.jsx("span",{className:"ct tabular",style:{color:v===f.length?"var(--success)":"var(--text-muted)"},children:v+" / "+f.length+" met"})]}),r.jsx("div",{className:"row gap-4",style:{marginBottom:12},children:f.map(k=>{const C=h(k),_=fe[C]??fe.info;return r.jsx("div",{title:Fc(k.id)+" · "+Fg(C),style:{flex:1,height:4,borderRadius:999,background:_.color,opacity:C==="pending"?.25:.9}},k.id)})}),r.jsx("div",{className:"card",style:{overflow:"hidden"},children:f.map(k=>r.jsxs("div",{className:"sp-crit",children:[r.jsx($g,{state:h(k)}),r.jsx("span",{className:"sp-crit-id",children:Fc(k.id)}),r.jsx("span",{className:"sp-crit-text",dangerouslySetInnerHTML:{__html:Rs(k.body||k.title)}})]},k.id))})]}),r.jsxs("div",{className:"sp-sec",children:[r.jsxs("div",{className:"sp-label",children:["Linked code",a.length>0&&r.jsx("span",{className:"ct",children:a.length+(a.length===1?" symbol":" symbols")})]}),a.length?r.jsx("div",{className:"card",style:{overflow:"hidden"},children:a.map((k,C)=>r.jsxs("div",{className:"row gap-10",style:{padding:"11px 14px",borderTop:C?"1px solid var(--border-subtle)":"none"},children:[r.jsx(Ge,{state:k.state}),k.driftAxis&&r.jsx(re,{color:"var(--warn)",bg:"var(--warn-soft)",children:k.driftAxis+" drift"}),r.jsx("span",{className:"mono grow",style:{fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:y(k)}),r.jsx(re,{children:k.provenance||"—"}),r.jsxs("button",{className:"btn btn-ghost btn-xs",onClick:()=>w(k),title:"Reveal in the graph",children:[r.jsx(z,{name:"reveal",size:12}),"Reveal"]})]},C))}):r.jsxs("div",{className:"card card-pad",style:{textAlign:"center",color:"var(--error)",borderColor:"rgba(242,85,90,0.3)"},children:[r.jsx(z,{name:"drift",size:16}),r.jsx("div",{style:{marginTop:6,fontSize:12.5},children:"Orphaned — no code implements this requirement yet"})]})]}),r.jsxs("div",{className:"row gap-8",style:{flexWrap:"wrap",marginTop:4},children:[r.jsxs("button",{className:"btn btn-primary btn-sm",disabled:!0,title:"Run automatically by the implementation workflow once Drafted",children:[r.jsx(z,{name:"play",size:13}),"Implement"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",disabled:!0,title:"Run automatically by the verification workflow",children:[r.jsx(z,{name:"check",size:13}),"Verify"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",disabled:!d,title:u,onClick:d?n:void 0,children:[r.jsx(z,{name:"reveal",size:13}),"Edit spec"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>B("graph",{query:{focus:"spec:"+s.id}}),children:[r.jsx(z,{name:"graph",size:13}),"Show in graph"]})]})]})})}const Yg=["pending","implementing","implemented","verified","drifted","broken"],Gg=["P0","P1","P2","P3"],qg=["requirement","constraint","guideline","invariant","non-functional"];function Xg(e,t){const{spec:n,childLinks:s}=e,l=typeof n.metadata?.rationale=="string"?n.metadata.rationale:typeof n.rationale=="string"?n.rationale:"";return{title:t.title,priority:n.priority??"",kind:n.kind??"requirement",owner:n.owner??"",statement:t.statement,rationale:l,criteria:t.criteria.map(o=>({id:o.id,state:sl(s[o.id],"pending"),text:o.text}))}}const Jg={title:"",priority:"",kind:"requirement",owner:"",statement:"",rationale:"",criteria:[]};function mn({label:e,hint:t,children:n}){return r.jsxs("div",{style:{marginBottom:22},children:[r.jsx("label",{className:"sp-fl",children:e}),n,t&&r.jsx("div",{className:"muted",style:{fontSize:11,marginTop:6},children:t})]})}function Zg({value:e,onChange:t,options:n,label:s}){const l=n.includes(e)?n:[e,...n];return r.jsx("select",{className:"input sp-select","aria-label":s,value:e,onChange:o=>t(o.target.value),style:{width:"100%",textTransform:"capitalize"},children:l.map(o=>r.jsx("option",{value:o,children:o},o))})}function ev({value:e,onChange:t,options:n,width:s,label:l}){const o=fe[e]??fe.info;return r.jsxs("div",{className:"row",style:{position:"relative",width:s??"auto",flexShrink:0},children:[r.jsx("span",{className:"pill-dot","data-testid":"crit-state-dot",style:{background:o.color,position:"absolute",left:11,pointerEvents:"none",zIndex:1}}),r.jsx("select",{className:"input sp-select","aria-label":l,value:e,onChange:a=>t(a.target.value),style:{width:"100%",paddingLeft:26,textTransform:"capitalize"},children:n.map(a=>r.jsx("option",{value:a,children:fe[a]?.label??a},a))})]})}function tv({state:e}){return r.jsxs("div",{className:"sp-status-auto",children:[e==="drafted"?r.jsxs(r.Fragment,{children:[r.jsx(Ge,{state:"drafted"}),r.jsx("span",{className:"muted",style:{fontSize:12},children:"queued for implementation"})]}):r.jsxs(r.Fragment,{children:[r.jsx(Ge,{state:e}),r.jsx(z,{name:"arrowRight",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx(Ge,{state:"drafted"})]}),r.jsx("span",{className:"grow"}),r.jsx(z,{name:"lock",size:12,style:{color:"var(--text-faint)",flexShrink:0}})]})}function nv({criteria:e,onChange:t}){const n=(s,l)=>t(e.map((o,a)=>a===s?{...o,...l}:o));return r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"row",style:{marginBottom:10,gap:10},children:[r.jsx("span",{className:"eyebrow",children:"Acceptance criteria"}),r.jsx("span",{style:{flex:1,height:1,background:"var(--border-subtle)"}}),r.jsx("span",{className:"mono tabular muted",style:{fontSize:11.5},children:e.length+" total"})]}),r.jsx("div",{className:"card",style:{overflow:"hidden",marginBottom:12},children:e.length===0?r.jsx("div",{className:"muted",style:{fontSize:12.5,textAlign:"center",padding:"18px 14px"},children:"No criteria yet — add one below."}):e.map((s,l)=>r.jsxs("div",{className:"sp-crit-edit",children:[r.jsx("span",{className:"sp-crit-grip",children:r.jsx(z,{name:"grip",size:14})}),r.jsx("span",{className:"sp-crit-num",children:"A"+(l+1)}),r.jsx(ev,{value:s.state,onChange:o=>n(l,{state:o}),options:Yg,width:156,label:"Criterion A"+(l+1)+" state"}),r.jsx("input",{className:"input grow",style:{fontSize:13},value:s.text,"aria-label":"Criterion A"+(l+1)+" text",placeholder:"Observable, testable condition…",onChange:o=>n(l,{text:o.target.value})}),r.jsx("button",{className:"sp-icon-btn",title:"Remove criterion","aria-label":"Remove criterion A"+(l+1),onClick:()=>t(e.filter((o,a)=>a!==l)),children:r.jsx(z,{name:"trash",size:14})})]},l))}),r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>t([...e,{id:"",state:"pending",text:""}]),children:[r.jsx(z,{name:"plus",size:13}),"Add criterion"]})]})}function rv({data:e,project:t,onCancel:n,onSaved:s}){const{spec:l}=e,o=e.parent?.sourcePath??l.sourcePath??"",a=N.useMemo(()=>Dp(e.source??"",l.id),[e.source,l.id]),[i,c]=N.useState(()=>a?Xg(e,a):Jg),d=N.useRef(JSON.stringify(i)),u=JSON.stringify(i)!==d.current,[f,h]=N.useState("write"),[g,v]=N.useState(!1),[p,j]=N.useState(null),m=k=>c(C=>({...C,...k})),x=sl(e.links,"drafted"),y=(fe[x]??fe.info).color;if(!a)return r.jsx(ue,{icon:"drift",title:"Can’t edit this spec",body:"Its requirement section couldn’t be located in the source file."});const w=async()=>{if(!u||g)return;const k=Ig({title:i.title,statement:i.statement,criteria:i.criteria}),C=Ag(e.source??"",l.id,k);if(C===null){j("Could not locate this requirement’s section in the source file.");return}v(!0),j(null);try{const _=await P.specSave(l.id,C,t);s(_.syncError??null)}catch(_){j(_ instanceof Error?_.message:String(_)),v(!1)}},S=r.jsxs("button",{className:"btn btn-primary btn-sm",disabled:!u||g,onClick:w,children:[r.jsx(z,{name:"check",size:13}),g?"Saving…":"Save changes"]});return r.jsxs("div",{className:"col",style:{flex:1,minHeight:0},children:[r.jsxs("div",{className:"sp-edit-bar",children:[r.jsx(z,{name:"reveal",size:15,style:{color:"var(--accent)",flexShrink:0}}),r.jsxs("div",{className:"col",style:{gap:1,minWidth:0},children:[r.jsx("div",{style:{fontSize:13,fontWeight:600},children:"Editing spec"}),r.jsx("div",{className:"mono muted",style:{fontSize:11,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:o+" · "+l.id})]}),r.jsx("div",{className:"grow"}),u&&r.jsxs("div",{className:"row gap-6",style:{marginRight:4},children:[r.jsx("span",{className:"sp-dirty-dot"}),r.jsx("span",{className:"muted",style:{fontSize:11.5},children:"Unsaved changes"})]}),r.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:n,children:[r.jsx(z,{name:"x",size:13}),"Cancel"]}),S]}),r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"24px 28px 56px"},children:r.jsxs("div",{style:{maxWidth:780},children:[p&&r.jsxs("div",{className:"card card-pad row gap-8",role:"alert",style:{color:"var(--error)",borderColor:"rgba(242,85,90,0.35)",marginBottom:18,fontSize:12.5},children:[r.jsx(z,{name:"cancel",size:14,style:{flexShrink:0}}),r.jsxs("span",{children:["Save failed — ",p," Your draft is intact."]})]}),r.jsx(mn,{label:"Title",children:r.jsx("input",{className:"input sp-input-lg",value:i.title,"aria-label":"Title",placeholder:"Short, imperative requirement title",onChange:k=>m({title:k.target.value})})}),r.jsxs("div",{className:"sp-edit-grid",children:[r.jsx(mn,{label:"Status",hint:"Set automatically — saving re-queues this spec as Drafted so the implementation workflow picks it up.",children:r.jsx(tv,{state:x})}),r.jsx(mn,{label:"Priority",children:r.jsx(Ce,{options:Gg,value:i.priority,onChange:k=>m({priority:k}),label:"Priority"})}),r.jsx(mn,{label:"Kind",children:r.jsx(Zg,{value:i.kind,onChange:k=>m({kind:k}),options:qg,label:"Kind"})}),r.jsx(mn,{label:"Owner",children:r.jsx("input",{className:"input mono",style:{width:"100%"},value:i.owner,"aria-label":"Owner",placeholder:"unassigned",onChange:k=>m({owner:k.target.value})})})]}),r.jsx("div",{className:"muted",style:{fontSize:11,margin:"-8px 0 22px"},children:"Priority, kind, and owner are document-level in the current spec format — they render from available data but aren’t persisted per-requirement yet."}),r.jsxs("div",{style:{marginBottom:22},children:[r.jsxs("div",{className:"row",style:{marginBottom:7},children:[r.jsx("label",{className:"sp-fl",style:{marginBottom:0},children:"Normative statement"}),r.jsx("div",{className:"grow"}),r.jsx(Ce,{size:"sm",options:[{value:"write",label:"Write"},{value:"preview",label:"Preview"}],value:f,onChange:h,label:"Statement editor mode"})]}),f==="write"?r.jsx("textarea",{className:"input sp-textarea",value:i.statement,spellCheck:!1,"aria-label":"Normative statement",placeholder:"The server MUST validate … (use MUST / SHOULD / MAY, **bold**, and `code`)",onChange:k=>m({statement:k.target.value})}):r.jsx("div",{className:"sp-statement",style:{"--sp-accent":y},children:i.statement.trim()?r.jsx("div",{className:"sp-prose",dangerouslySetInnerHTML:{__html:Rs(i.statement)}}):r.jsx("div",{className:"muted",style:{fontSize:13},children:"Nothing to preview yet."})}),r.jsxs("div",{className:"sp-kw-legend",children:[r.jsx("span",{className:"label",children:"Keywords:"}),r.jsx("span",{className:"sp-kw sp-kw-must",children:"MUST"}),r.jsx("span",{className:"sp-kw sp-kw-should",children:"SHOULD"}),r.jsx("span",{className:"sp-kw sp-kw-may",children:"MAY"}),r.jsx("span",{className:"label",style:{marginLeft:4},children:"auto-highlight as you type"})]})]}),r.jsx(mn,{label:"Rationale",hint:"Optional — why this requirement exists. Presentation-only today: the spec format carries no per-requirement rationale field.",children:r.jsx("textarea",{className:"input sp-textarea",value:i.rationale,spellCheck:!1,style:{minHeight:84},"aria-label":"Rationale",placeholder:"Why does this matter? What breaks without it?",onChange:k=>m({rationale:k.target.value})})}),r.jsx(nv,{criteria:i.criteria,onChange:k=>m({criteria:k})}),r.jsxs("div",{className:"row",style:{gap:10,marginTop:32,paddingTop:20,borderTop:"1px solid var(--border-subtle)"},children:[S,r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:n,children:"Cancel"}),r.jsx("div",{className:"grow"}),r.jsx("span",{className:"mono muted",style:{fontSize:11},children:u?"edited":"no changes"})]})]})})]})}function Hc(e){return t=>{(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),e())}}function sv(e){const t=new Map,n=new Map(e.map(l=>[l.id,l])),s=(l,o)=>{let a=t.get(l);return a||(a={doc:o,path:l,reqs:[]},t.set(l,a)),o&&!a.doc&&(a.doc=o),a};for(const l of e)l.kind==="document"&&s(l.sourcePath??l.id,l);for(const l of e){if(l.kind!=="requirement")continue;const o=l.parentId?n.get(l.parentId):void 0,a=o?.sourcePath??l.sourcePath??"(unknown)";s(a,o?.kind==="document"?o:null).reqs.push(l)}return[...t.values()]}const lv=["verified","implemented","drifted","broken","orphaned"];function ov({project:e,param:t,query:n}){const s=L(()=>P.specs(e),[e]),[l,o]=N.useState(t??n.sel??null);N.useEffect(()=>{const p=t??n.sel;p&&o(p)},[t,n.sel]);const[a,i]=N.useState(new Set),c=N.useRef(new Map).current,d=N.useMemo(()=>sv(s.data?.specs??[]),[s.data]),u=s.data?.linkStates??{};if(Kt(s.error))return r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."});const f=d.reduce((p,j)=>p+j.reqs.length,0),h={};for(const p of d)for(const j of p.reqs){const m=u[j.id];m&&(h[m]=(h[m]??0)+1)}const g=p=>{const j=u[p.id];return!!j&&a.has(j)},v=p=>i(j=>{const m=new Set(j);return m.has(p)?m.delete(p):m.add(p),m});return r.jsxs("div",{style:{flex:1,display:"flex",minHeight:0},children:[r.jsxs("div",{className:"col",style:{width:280,flexShrink:0,borderRight:"1px solid var(--border-subtle)",background:"var(--bg-panel)"},children:[r.jsxs("div",{className:"row",style:{gap:8,padding:"11px 12px",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"book",size:15,style:{color:"var(--accent)"}}),r.jsx("span",{style:{fontWeight:600,fontSize:13},children:"Specs"}),r.jsx("span",{className:"grow"}),r.jsx("span",{className:"muted tabular",style:{fontSize:11},children:s.data?f+" reqs":"…"})]}),r.jsxs("div",{className:"row",style:{gap:5,padding:"8px 10px",flexWrap:"wrap",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"filter",size:12,style:{color:"var(--text-muted)",flexShrink:0}}),lv.map(p=>{const j=!a.has(p),m=fe[p];return r.jsxs("button",{onClick:()=>v(p),className:"row gap-4",style:{height:22,padding:"0 8px",borderRadius:999,fontSize:10.5,fontWeight:500,cursor:"pointer",textTransform:"capitalize",border:"1px solid "+(j?"transparent":"var(--border-subtle)"),background:j?m.bg:"var(--bg-panel)",color:j?m.color:"var(--text-muted)"},children:[p,r.jsx("span",{className:"tabular",style:{opacity:.7},children:h[p]??0})]},p)})]}),r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:6},role:d.length?"tree":void 0,"aria-label":d.length?"Spec tree":void 0,children:[s.data&&!d.length&&r.jsx(ue,{icon:"book",title:"No specs yet",body:"Author one with the spec-author skill — specs/*.md index on sync."}),d.map(p=>r.jsx(av,{group:p,linkStates:u,selId:l,hidden:g,onSel:o},p.path))]})]}),r.jsx("div",{className:"col",style:{flex:1,minWidth:0},children:r.jsx(Hg,{id:l,project:e,cache:c},l??"")})]})}function av({group:e,linkStates:t,selId:n,hidden:s,onSel:l}){const[o,a]=N.useState(!0),i=e.reqs.filter(d=>!s(d)),c=e.reqs.filter(d=>["drifted","broken","orphaned"].includes(t[d.id]??"")).length;return r.jsxs("div",{children:[r.jsxs("div",{onClick:()=>a(!o),onKeyDown:Hc(()=>a(!o)),role:"treeitem","aria-expanded":o,tabIndex:0,className:"row gap-6 list-row",style:{padding:"6px 8px",borderRadius:6,cursor:"pointer",color:"var(--text-secondary)"},children:[r.jsx(z,{name:o?"chevronDown":"chevronRight",size:12,style:{color:"var(--text-muted)"}}),r.jsx(z,{name:"book",size:13,style:{color:"var(--node-spec)"}}),r.jsx("span",{className:"mono grow",style:{fontSize:12,color:"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.path.replace(/^specs\//,"")}),c>0&&r.jsx("span",{className:"pill",style:{fontSize:9.5,color:"var(--warn)",background:"var(--warn-soft)"},children:c})]}),o&&i.length>0&&r.jsx("div",{role:"group",style:{marginLeft:14,borderLeft:"1px solid var(--border-subtle)",paddingLeft:6},children:i.map(d=>{const u=n===d.id,f=fe[t[d.id]??""]??fe.drafted;return r.jsxs("div",{onClick:()=>l(d.id),onKeyDown:Hc(()=>l(d.id)),role:"treeitem","aria-selected":u,tabIndex:0,className:"row gap-6 list-row"+(u?" selected":""),style:{padding:"5px 8px",borderRadius:6,cursor:"pointer"},children:[r.jsx("span",{className:"pill-dot",style:{background:f.color,flexShrink:0}}),r.jsxs("div",{className:"grow",style:{minWidth:0},children:[r.jsx("div",{className:"mono",style:{fontSize:11,color:u?"var(--accent)":"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.id}),r.jsx("div",{className:"muted",style:{fontSize:10.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.title})]})]},d.id)})})]})}const Uc={error:0,warn:1,info:2},iv=e=>e==="error"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)";function cv({query:e,tips:t,onSetTipState:n}){const s=L(()=>P.claudeStats(),[]),l=s.data?.sessionCount===0,o=e.sel,a=t.data?.tips??[],i=[...a].sort((d,u)=>(Uc[d.severity]??9)-(Uc[u.severity]??9)),c=d=>a.filter(u=>u.severity===d&&u.state!=="applied").length;return r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:18},children:[r.jsx(Ae,{icon:"tips",title:"Tips",sub:"A senior teammate reviewed your transcripts",actions:a.length>0&&r.jsxs("div",{className:"row gap-6",children:[r.jsxs(re,{color:"var(--error)",bg:"var(--error-soft)",children:[c("error")," urgent"]}),r.jsxs(re,{color:"var(--warn)",bg:"var(--warn-soft)",children:[c("warn")," warn"]}),r.jsxs(re,{color:"var(--info)",bg:"var(--info-soft)",children:[c("info")," info"]})]})}),l&&!a.length?r.jsx(Fn,{onIngested:()=>{s.reload(),t.reload()}}):r.jsx(ae,{state:t,label:"tips",minHeight:240,children:d=>d.tips.length?r.jsx("div",{className:"col gap-12",style:{maxWidth:860},children:i.map(u=>r.jsx(dv,{tip:u,focus:u.id===o,onApply:()=>n(u.id,"applied"),onDismiss:()=>n(u.id,"dismissed")},u.id))}):r.jsx("div",{className:"muted",style:{fontSize:12.5,padding:8},children:"No tips — nothing wasteful in your recent sessions."})})]})}function dv({tip:e,focus:t,onApply:n,onDismiss:s}){const[l,o]=N.useState(!1),a=N.useRef(null);N.useEffect(()=>{if(!t||!a.current)return;const d=a.current,u=d.closest(".scroll-y");u&&(u.scrollTop=Math.max(0,d.offsetTop-20)),o(!0);const f=setTimeout(()=>o(!1),1800);return()=>clearTimeout(f)},[t]);const i=iv(e.severity),c=e.state==="applied";return r.jsxs("div",{ref:a,className:"card",style:{display:"flex",opacity:c?.7:1,transition:"box-shadow var(--motion-fast), border-color var(--motion-fast)",boxShadow:l?`0 0 0 2px ${i}`:"none",borderColor:l?i:void 0},children:[r.jsx("div",{style:{width:3,background:i,flexShrink:0,borderRadius:"9px 0 0 9px"}}),r.jsxs("div",{style:{padding:"14px 16px",flex:1,minWidth:0},children:[r.jsxs("div",{className:"row gap-10",style:{marginBottom:10},children:[r.jsx("div",{style:{width:28,height:28,borderRadius:8,background:`color-mix(in srgb, ${i} 16%, transparent)`,display:"grid",placeItems:"center",color:i,flexShrink:0},children:r.jsx(z,{name:e.icon,size:15})}),r.jsx("div",{className:"grow",style:{minWidth:0},children:r.jsx("div",{style:{fontSize:14,fontWeight:600,letterSpacing:"-0.01em",textWrap:"pretty"},children:e.title})}),r.jsx(re,{color:i,bg:`color-mix(in srgb, ${i} 14%, transparent)`,children:e.severity})]}),r.jsx("div",{className:"secondary",style:{fontSize:12.5,lineHeight:1.6,marginBottom:12},children:e.why}),r.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:14},children:[r.jsxs("div",{onClick:()=>B("sessions",{query:{sel:e.evidence.session}}),role:"button",tabIndex:0,onKeyDown:d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),B("sessions",{query:{sel:e.evidence.session}}))},title:"Open session "+e.evidence.session,className:"list-row",style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:8,padding:10,cursor:"pointer"},children:[r.jsxs("div",{className:"row gap-6",style:{marginBottom:5},children:[r.jsx("span",{className:"eyebrow",children:"Evidence"}),r.jsx("span",{className:"grow"}),r.jsx(z,{name:"arrowRight",size:11,style:{color:"var(--text-muted)"}})]}),r.jsxs("div",{className:"row gap-6",style:{fontSize:11.5},children:[r.jsx(z,{name:"sessions",size:11,style:{color:"var(--text-muted)"}}),r.jsx("span",{className:"mono",style:{color:"var(--accent)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.evidence.session})]}),r.jsx("div",{className:"mono secondary",style:{fontSize:11,marginTop:4,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.evidence.detail})]}),r.jsxs("div",{style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:8,padding:10},children:[r.jsx("div",{className:"eyebrow",style:{marginBottom:5},children:"Impact"}),r.jsx("div",{className:"tabular",style:{fontSize:16,fontWeight:700,color:"var(--success)"},children:e.saving})]})]}),r.jsxs("div",{className:"row gap-8",style:{alignItems:"center"},children:[r.jsxs("div",{className:"row gap-8 grow",style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:7,padding:"6px 10px",minWidth:0},children:[r.jsx("span",{className:"muted",style:{fontSize:10.5,flexShrink:0},children:"fix"}),r.jsx("code",{className:"mono grow",style:{fontSize:11.5,color:"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.fix}),r.jsx(pt,{text:e.fix})]}),c?r.jsxs("span",{className:"pill",style:{color:"var(--success)",background:"var(--success-soft)"},children:[r.jsx(z,{name:"check",size:11}),"Applied"]}):r.jsx("button",{className:"btn btn-primary btn-sm",onClick:n,title:"Mark applied",children:"Apply"}),r.jsx("button",{className:"btn btn-secondary btn-sm",onClick:s,title:"Dismiss — this tip won't come back",children:"Dismiss"})]})]})]})}const uv={bundled:"var(--node-spec)",global:"var(--node-code)",project:"var(--node-route)"};function pv({project:e,query:t}){const n=L(()=>P.workflows(e),[e]),s=n.data?.workflows??[],[l,o]=N.useState(t.run??null);if(Kt(n.error))return r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."});const a=l?s.find(i=>i.workflow.name===l):void 0;return r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:18},children:[r.jsx(Ae,{icon:"workflow",title:"Workflows",sub:n.data?"Run a YAML-defined DAG of agent, shell and approval steps":"Loading workflows…"}),n.data&&!s.length&&r.jsx(ue,{icon:"workflow",title:"No workflows found",body:"Add YAML definitions under .specship/workflows/ in this project or your home directory."}),r.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(340px, 1fr))",gap:12},children:s.map(({workflow:i,scope:c})=>{const d=uv[c]??"var(--text-secondary)";return r.jsxs("div",{className:"card card-pad",style:{display:"flex",flexDirection:"column",gap:10},children:[r.jsxs("div",{className:"row gap-8",children:[r.jsx("span",{className:"mono",style:{fontSize:13.5,fontWeight:600},children:i.name}),r.jsx(re,{color:d,bg:`color-mix(in srgb, ${d} 14%, transparent)`,children:c}),r.jsx("span",{className:"grow"}),r.jsxs("span",{className:"mono muted tabular",style:{fontSize:10.5},children:[i.nodes.length," nodes"]})]}),r.jsx("div",{className:"secondary",style:{fontSize:12.5,lineHeight:1.5,minHeight:36},children:i.description||"No description."}),r.jsxs("div",{className:"row gap-6",style:{flexWrap:"wrap",borderTop:"1px solid var(--border-subtle)",paddingTop:10},children:[(i.requires??[]).length>0&&r.jsx("span",{className:"muted",style:{fontSize:10.5},children:"requires"}),(i.requires??[]).map(u=>r.jsx("code",{className:"mono",style:{fontSize:10.5,color:"var(--text-secondary)",background:"var(--bg-canvas)",padding:"1px 6px",borderRadius:4},children:u},u)),(i.inputs??[]).length>0&&r.jsxs(r.Fragment,{children:[r.jsx("span",{className:"muted",style:{fontSize:10.5,marginLeft:6},children:"inputs"}),(i.inputs??[]).map(u=>r.jsxs("code",{className:"mono",style:{fontSize:10.5,color:"var(--node-spec)",background:"var(--node-spec-soft)",padding:"1px 6px",borderRadius:4},children:["$",u.name]},u.name))]}),r.jsx("span",{className:"grow"}),r.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>o(i.name),children:[r.jsx(z,{name:"play",size:13}),"Launch"]})]})]},i.name)})}),a&&r.jsx(fv,{wf:a.workflow,project:e,onClose:()=>o(null)})]})}function fv({wf:e,project:t,onClose:n}){const s=e.inputs??[],[l,o]=N.useState(()=>Object.fromEntries(s.filter(h=>h.default).map(h=>[h.name,h.default]))),[a,i]=N.useState(!1),[c,d]=N.useState(null),u=s.filter(h=>h.required&&!(l[h.name]??"").trim()),f=()=>{if(a||u.length)return;i(!0),d(null);const h=Object.fromEntries(Object.entries(l).filter(([,g])=>g.trim()));P.launchRun(e.name,h,t).then(g=>B("runs",{param:g.runId}),g=>{d(g instanceof Error?g.message:String(g)),i(!1)})};return r.jsx("div",{onMouseDown:n,role:"dialog","aria-label":"Launch "+e.name,style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.5)",zIndex:90,display:"grid",placeItems:"center"},children:r.jsxs("div",{onMouseDown:h=>h.stopPropagation(),style:{width:460,maxWidth:"90vw",background:"var(--bg-elevated)",border:"1px solid var(--border-strong)",borderRadius:12,boxShadow:"var(--shadow-pop)"},children:[r.jsxs("div",{className:"row gap-10",style:{padding:"14px 16px",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"workflow",size:16,style:{color:"var(--accent)"}}),r.jsx("span",{className:"mono grow",style:{fontWeight:600},children:e.name}),r.jsx("button",{className:"btn btn-ghost btn-xs",onClick:n,"aria-label":"Close",children:r.jsx(z,{name:"x",size:14})})]}),r.jsxs("div",{style:{padding:16},children:[r.jsx("div",{className:"secondary",style:{fontSize:12.5,marginBottom:16,lineHeight:1.55},children:e.description||"No description."}),s.length?s.map(h=>r.jsxs("div",{style:{marginBottom:12},children:[r.jsxs("label",{className:"eyebrow",style:{display:"block",marginBottom:5},htmlFor:"wf-input-"+h.name,children:[h.name,h.required&&r.jsx("span",{style:{color:"var(--error)"},children:" *"})]}),r.jsx("input",{id:"wf-input-"+h.name,className:"input mono",style:{width:"100%"},placeholder:h.description||(h.name==="SPEC_ID"?"REQ-AUTH-005":"value…"),value:l[h.name]||"",onChange:g=>o(v=>({...v,[h.name]:g.target.value})),onKeyDown:g=>{g.key==="Enter"&&f()}})]},h.name)):r.jsx("div",{className:"muted",style:{fontSize:12,padding:"8px 0"},children:"No inputs required."}),r.jsx("div",{className:"row gap-6",style:{marginTop:6,marginBottom:4},children:(e.requires??[]).map(h=>r.jsxs(re,{children:[r.jsx(z,{name:"check",size:10}),h]},h))}),c&&r.jsxs("div",{className:"row gap-8",style:{marginTop:8,padding:"8px 10px",borderRadius:7,background:"var(--error-soft)",color:"var(--error)",fontSize:12},children:[r.jsx(z,{name:"cancel",size:13,style:{flexShrink:0}}),r.jsx("span",{children:c})]})]}),r.jsxs("div",{className:"row gap-8",style:{padding:"12px 16px",borderTop:"1px solid var(--border-subtle)",justifyContent:"flex-end"},children:[r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:n,children:"Cancel"}),r.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,disabled:a||u.length>0,title:u.length?"Fill the required inputs: "+u.map(h=>h.name).join(", "):void 0,children:[r.jsx(z,{name:"play",size:13}),a?"Launching…":"Launch run"]})]})]})})}const xi=[{group:"Project",items:[{id:"dashboard",label:"Dashboard",icon:"dashboard"},{id:"graph",label:"Graph",icon:"graph"},{id:"specs",label:"Specs",icon:"book"},{id:"drift",label:"Drift queue",icon:"drift",badge:e=>e.drift},{id:"runs",label:"Runs",icon:"play",badge:e=>e.runs,badgeKind:"warn"}]},{group:"Claude Code",items:[{id:"sessions",label:"Sessions",icon:"sessions"},{id:"heatmap",label:"Heatmap",icon:"heatmap"},{id:"costs",label:"Costs",icon:"dollar"},{id:"compare",label:"Compare projects",icon:"compare"},{id:"memory",label:"Memory",icon:"memory"},{id:"mcp",label:"MCP",icon:"plug"},{id:"tips",label:"Tips",icon:"tips",badge:e=>e.tips,badgeKind:"error"}]}],hv=[...xi.flatMap(e=>e.items.map(({id:t,label:n,icon:s})=>({id:t,label:n,icon:s}))),{id:"workflows",label:"Workflows",icon:"workflow"},{id:"chat",label:"Chat",icon:"chat"},{id:"designsystem",label:"Design system",icon:"layers"},{id:"settings",label:"Settings",icon:"settings"}],mv=xi.flatMap(e=>e.items.map(t=>t.id)).slice(0,7),xv={dashboard:dx,graph:Ax,specs:ov,drift:Rx,runs:Sg,workflows:pv,chat:$m,designsystem:()=>r.jsx(Tx,{}),sessions:Ng,heatmap:Bx,costs:ax,compare:sx,memory:ag,mcp:eg,settings:e=>r.jsx(Og,{...e})},co="ss_project",Vc="ss_nav_groups",Kc="ss_nav_collapsed";function gv(){const{route:e,param:t,query:n}=hm(),[s,l]=N.useState(()=>{try{return localStorage.getItem(Kc)==="1"}catch{return!1}}),[o,a]=N.useState(()=>{try{return localStorage.getItem(co)}catch{return null}}),[i,c]=N.useState(!1),[d,u]=N.useState(!1),f=L(()=>P.status(o),[o,e]),h=L(()=>P.projects(),[]),g=L(()=>P.runs(o),[o,e]),v=L(()=>P.claudeTips(),[e]),p=L(()=>P.drift(o),[o,e]),j=N.useCallback(()=>u(_=>!_),[]);Cm({onTogglePalette:j,pageIds:mv});const m={drift:p.data?.links.length??f.data?.drift??0,runs:g.data?.runs.filter(_=>_.status==="running").length??0,tips:v.data?.tips.filter(_=>_.state!=="applied").length??0},x=N.useCallback(()=>u(!0),[]),y=N.useCallback((_,W)=>{P.setTipState(_,W).catch(()=>{}).finally(()=>v.reload())},[v.reload]),w=()=>l(_=>{try{localStorage.setItem(Kc,_?"0":"1")}catch{}return!_}),S=_=>{a(_);try{_?localStorage.setItem(co,_):localStorage.removeItem(co)}catch{}},k=()=>{c(!0),P.refresh(o).catch(()=>{}).finally(()=>{c(!1),f.reload()})},C=xv[e]??(()=>r.jsx(ig,{title:"Not found"}));return r.jsxs("div",{style:{display:"flex",height:"100%",position:"relative"},children:[r.jsx(vv,{route:e,collapsed:s,counts:m,onToggleCollapse:w}),r.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",minWidth:0},children:[r.jsx(jv,{status:f.data,projectless:Kt(f.error),projects:h.data?.projects??[],project:o,onPick:S,onRefresh:k,refreshing:i}),r.jsx(Sv,{onToggle:w,onOpenPalette:x}),r.jsx("div",{"data-screen":e,style:{flex:1,minHeight:0,display:"flex",flexDirection:"column"},children:e==="tips"?r.jsx(cv,{project:o,param:t,query:n,tips:v,onSetTipState:y}):r.jsx(C,{project:o,param:t,query:n})},e+(t??""))]}),r.jsx(Sm,{open:d,onClose:()=>u(!1),pages:hv,project:o})]})}function vv({route:e,collapsed:t,counts:n,onToggleCollapse:s}){const[l,o]=N.useState(()=>{try{return JSON.parse(localStorage.getItem(Vc)||"null")||{}}catch{return{}}}),a=c=>l[c]!==!1,i=c=>o(d=>{const u={...d,[c]:d[c]===!1};try{localStorage.setItem(Vc,JSON.stringify(u))}catch{}return u});return r.jsxs("nav",{style:{width:t?"var(--sidebar-w-collapsed)":"var(--sidebar-w)",flexShrink:0,background:"var(--bg-panel)",borderRight:"1px solid var(--border-subtle)",display:"flex",flexDirection:"column",transition:"width 120ms",overflow:"hidden"},children:[r.jsxs("div",{className:"row gap-8",onClick:s,title:t?"Expand menu":"Collapse menu",style:{padding:t?"14px 0":"15px 16px",justifyContent:t?"center":"flex-start",cursor:"pointer",userSelect:"none"},children:[r.jsx(ap,{size:26}),!t&&r.jsx("div",{className:"grow",style:{fontWeight:600,fontSize:13.5,letterSpacing:"-0.01em"},children:"SpecShip"})]}),r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"4px 8px"},children:xi.map(c=>r.jsxs("div",{style:{marginBottom:t?10:4},children:[!t&&r.jsxs("button",{onClick:()=>i(c.group),className:"row gap-6",style:{width:"100%",padding:"8px 8px 4px",background:"none",border:"none",cursor:"pointer",textAlign:"left"},children:[r.jsx("span",{className:"eyebrow grow",children:c.group}),r.jsx(z,{name:a(c.group)?"chevronDown":"chevronRight",size:12,style:{color:"var(--text-muted)"}})]}),(t||a(c.group))&&c.items.map(d=>r.jsx(uo,{item:d,active:e===d.id,collapsed:t,counts:n},d.id))]},c.group))}),r.jsxs("div",{style:{padding:8,borderTop:"1px solid var(--border-subtle)"},children:[r.jsx(uo,{item:{id:"designsystem",label:"Design system",icon:"layers"},active:e==="designsystem",collapsed:t}),r.jsx(uo,{item:{id:"settings",label:"Settings",icon:"settings"},active:e==="settings",collapsed:t})]})]})}function uo({item:e,active:t,collapsed:n,counts:s}){const l=i=>{i.metaKey||i.ctrlKey||i.shiftKey||i.button!==0||(i.preventDefault(),B(e.id))},o=e.badge&&s?e.badge(s):0,a=e.badgeKind;return r.jsxs("a",{href:"/"+e.id,onClick:l,title:n?e.label:void 0,className:"list-row",style:{display:"flex",alignItems:"center",gap:10,height:32,padding:n?0:"0 10px",justifyContent:n?"center":"flex-start",borderRadius:7,textDecoration:"none",marginBottom:1,color:t?"var(--text-primary)":"var(--text-secondary)",background:t?"var(--bg-active)":void 0,fontWeight:t?600:450,fontSize:13,position:"relative"},children:[t&&r.jsx("span",{style:{position:"absolute",left:0,top:7,bottom:7,width:2.5,borderRadius:2,background:"var(--accent)"}}),r.jsx(z,{name:e.icon,size:16,style:{color:t?"var(--accent)":"inherit",flexShrink:0}}),!n&&r.jsx("span",{className:"grow",style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.label}),!n&&o>0&&r.jsx("span",{className:"pill tabular",style:{fontSize:10,fontWeight:700,padding:"1px 6px",minWidth:18,justifyContent:"center",color:a==="error"?"var(--error)":a==="warn"?"var(--warn)":"var(--text-secondary)",background:a==="error"?"var(--error-soft)":a==="warn"?"var(--warn-soft)":"rgba(255,255,255,0.06)"},children:o}),n&&o>0&&r.jsx("span",{style:{position:"absolute",top:5,right:9,width:6,height:6,borderRadius:"50%",background:a==="error"?"var(--error)":"var(--warn)"}})]})}function yv({projects:e,project:t,projectPath:n,onPick:s}){const[l,o]=N.useState(!1),a=N.useRef(null),[i,c]=N.useState(null),d=()=>{if(!l){const g=a.current?.getBoundingClientRect();c(g?{top:g.bottom+5,left:g.left}:null)}o(g=>!g)};N.useEffect(()=>{if(!l)return;const g=v=>{v.target.closest("[data-projsw]")||o(!1)};return window.addEventListener("mousedown",g),()=>window.removeEventListener("mousedown",g)},[l]);const u=e.filter(g=>g.initialized),f=t??"",h=n||(t??"pick a project");return r.jsxs("div",{"data-projsw":"1",style:{position:"relative",flexShrink:0},children:[r.jsxs("button",{ref:a,onClick:d,className:"row gap-6",title:"Switch project",style:{height:24,padding:"0 8px",borderRadius:6,cursor:"pointer",background:l?"var(--bg-hover)":"transparent",border:"1px solid "+(l?"var(--border-strong)":"transparent"),transition:"background var(--motion-fast), border-color var(--motion-fast)"},children:[r.jsx(z,{name:"folder",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"mono",style:{fontSize:11.5,color:"var(--text-primary)",maxWidth:280,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:h}),r.jsx(z,{name:"chevronDown",size:12,style:{color:"var(--text-muted)",flexShrink:0}})]}),l&&r.jsxs("div",{style:{position:"fixed",top:i?.top??34,left:i?.left??8,minWidth:264,background:"var(--bg-elevated)",border:"1px solid var(--border-strong)",borderRadius:9,boxShadow:"var(--shadow-pop)",padding:5,zIndex:60},children:[r.jsx("div",{className:"eyebrow",style:{padding:"5px 8px 6px"},children:"Indexed projects"}),r.jsxs("button",{className:"row gap-8",onClick:()=>{s(null),o(!1)},style:Qc(f===""),children:[r.jsx(z,{name:"folder",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"grow",style:{textAlign:"left",fontSize:12.5},children:"Primary project"}),f===""&&r.jsx(z,{name:"check",size:13,style:{color:"var(--accent)",flexShrink:0}})]}),u.map(g=>{const v=g.slug===f;return r.jsxs("button",{className:"row gap-8",onClick:()=>{s(g.slug),o(!1)},style:Qc(v),children:[r.jsx(z,{name:"folder",size:13,style:{color:v?"var(--accent)":"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"grow mono",style:{textAlign:"left",fontSize:11.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:g.path}),(g.driftCount??0)>0&&r.jsxs("span",{className:"pill tabular",style:{fontSize:9.5,color:"var(--warn)",background:"var(--warn-soft)",flexShrink:0},children:[g.driftCount," drift"]}),v&&r.jsx(z,{name:"check",size:13,style:{color:"var(--accent)",flexShrink:0}})]},g.slug)}),!u.length&&r.jsx("div",{className:"muted",style:{padding:"6px 8px",fontSize:12},children:"No initialized projects found."})]})]})}function Qc(e){return{width:"100%",textAlign:"left",padding:"7px 8px",borderRadius:6,cursor:"pointer",border:"none",background:e?"var(--bg-active)":"transparent"}}function jv({status:e,projectless:t,projects:n,project:s,onPick:l,onRefresh:o,refreshing:a}){const i=(u,f,h)=>r.jsxs("div",{className:"row gap-6",style:{flexShrink:0},children:[r.jsx("span",{className:"muted",style:{fontSize:11},children:u}),r.jsx("span",{className:"mono tabular",style:{fontSize:11.5,color:h||"var(--text-secondary)"},children:f})]}),c=r.jsx("span",{style:{width:1,height:12,background:"var(--border-subtle)",flexShrink:0}}),d=e?.lastIndexed?new Date(e.lastIndexed).toLocaleString():"—";return r.jsxs("div",{style:{height:"var(--status-h)",flexShrink:0,display:"flex",alignItems:"center",gap:14,padding:"0 14px",borderBottom:"1px solid var(--border-subtle)",background:"var(--bg-panel-2)",overflow:"hidden",whiteSpace:"nowrap"},children:[r.jsx(yv,{projects:n,project:s,projectPath:e?.projectPath??null,onPick:l}),c,i("nodes",e?e.nodeCount.toLocaleString():t?"—":"…"),i("edges",e?e.edgeCount.toLocaleString():t?"—":"…"),c,i("drift",e?String(e.drift):"—",e?e.drift?"var(--warn)":"var(--success)":void 0),r.jsx("div",{className:"grow"}),i("indexed",d),r.jsx("button",{className:"btn btn-ghost btn-xs",onClick:o,title:"Refresh now","aria-label":"Refresh now",children:r.jsx(z,{name:"refresh",size:12,style:{animation:a?"spin 0.8s linear infinite":"none"}})})]})}const wv={fontFamily:"var(--font-mono)",fontSize:10,color:"var(--text-muted)",background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:4,padding:"2px 6px"};function Sv({onToggle:e,onOpenPalette:t}){return r.jsxs("div",{style:{height:44,flexShrink:0,display:"flex",alignItems:"center",gap:10,padding:"0 14px",borderBottom:"1px solid var(--border-subtle)",background:"var(--bg-canvas)"},children:[r.jsx("button",{className:"btn btn-ghost",onClick:e,style:{padding:6},title:"Toggle sidebar","aria-label":"Toggle sidebar",children:r.jsx(z,{name:"menu",size:16})}),r.jsxs("button",{onClick:t,className:"row gap-8",style:{flex:1,maxWidth:380,height:30,padding:"0 11px",background:"var(--bg-panel)",border:"1px solid var(--border-subtle)",borderRadius:8,cursor:"text",color:"var(--text-muted)",fontSize:12.5},children:[r.jsx(z,{name:"search",size:14}),r.jsx("span",{className:"grow",style:{textAlign:"left"},children:"Search or jump to…"}),r.jsx("kbd",{style:wv,children:"⌘K"})]}),r.jsx("div",{className:"grow"}),r.jsx(bv,{}),r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:t,title:"Command palette","aria-label":"Command palette",children:r.jsx(z,{name:"command",size:14})})]})}function bv(){const[e,t]=N.useState(Sl()),n={dark:"light",light:"system",system:"dark"},s={dark:"moon",light:"sun",system:"monitor"},l=n[e];return r.jsx("button",{className:"btn btn-ghost btn-sm",title:"Theme: "+e+" — switch to "+l,"aria-label":"Theme: "+e+" — switch to "+l,onClick:()=>{bl(l),t(l)},children:r.jsx(z,{name:s[e],size:15})})}bl(Sl());Tm();Rp(_p());po.createRoot(document.getElementById("root")).render(r.jsx(Jp.StrictMode,{children:r.jsx(gv,{})}));
51
+ `)}function Rs(e){let t=String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");return t=t.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),t=t.replace(/`([^`]+?)`/g,"<code class='sp-code'>$1</code>"),t=t.replace(/\b(MUST NOT|MUST|SHALL NOT|SHALL|REQUIRED)\b/g,"<span class='sp-kw sp-kw-must'>$1</span>"),t=t.replace(/\b(SHOULD NOT|SHOULD|RECOMMENDED)\b/g,"<span class='sp-kw sp-kw-should'>$1</span>"),t=t.replace(/\b(MAY|OPTIONAL)\b/g,"<span class='sp-kw sp-kw-may'>$1</span>"),t}const Bg=new Set(["verified","implemented","completed"]);function sl(e,t){if(!e||!e.length)return t;const n=e.map(s=>s.state);return n.includes("broken")?"broken":n.includes("orphaned")?"orphaned":n.includes("drifted")?"drifted":n.every(s=>s==="verified")?"verified":"implemented"}const Wg={verified:"check",implemented:"check",completed:"check",drifted:"drift",broken:"cancel",orphaned:"cancel",failed:"cancel"};function $g({state:e}){const t=fe[e]??fe.info,n=Wg[e];return r.jsx("div",{className:"sp-crit-mark",style:{background:t.bg,color:t.color},children:n?r.jsx(z,{name:n,size:12}):r.jsx("span",{style:{width:7,height:7,borderRadius:"50%",border:"1.6px solid "+t.color,boxSizing:"border-box"}})})}function Fc(e){const t=e.lastIndexOf(".");return t===-1?e:e.slice(t+1)}function Fg(e){return fe[e]?.label??e}function Hg({id:e,project:t,cache:n}){return e?r.jsx(Vg,{id:e,project:t,cache:n}):r.jsx(Ug,{})}function Ug(){return r.jsx(ue,{icon:"book",title:"Pick a spec from the tree",body:"Or run specship init -i to index your specs/ folder if you haven’t yet.",action:r.jsxs("span",{className:"row gap-6",style:{justifyContent:"center"},children:[r.jsx("code",{className:"mono",style:{fontSize:11.5,color:"var(--accent)",background:"var(--bg-canvas)",padding:"5px 10px",borderRadius:6,border:"1px solid var(--border-subtle)"},children:"specship init -i"}),r.jsx(pt,{text:"specship init -i"})]})})}function Vg({id:e,project:t,cache:n}){const s=(t??"")+"|"+e,l=L(async()=>{const u=await P.spec(e,t);return n?.set(s,u),u},[e,t]),o=l.data??n?.get(s)??null,[a,i]=N.useState(!1),[c,d]=N.useState(null);return N.useEffect(()=>{i(!1),d(null)},[e]),o?a?r.jsx(rv,{data:o,project:t,onCancel:()=>i(!1),onSaved:u=>{i(!1),d(u),l.reload()}}):r.jsx(Qg,{data:o,notice:c,onEdit:()=>{d(null),i(!0)}}):l.loading?r.jsx(Kg,{}):Kt(l.error)?r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."}):r.jsx(ue,{icon:"drift",title:`Couldn’t load ${e}`,body:l.error instanceof Error?l.error.message:"The spec detail request failed.",action:r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:l.reload,children:[r.jsx(z,{name:"refresh",size:13}),"Retry"]})})}function Kg(){return r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"28px 32px 56px"},"data-testid":"spec-skeleton",children:r.jsxs("div",{className:"sp-doc",children:[r.jsx("div",{className:"skel",style:{width:230,height:12,marginBottom:20}}),r.jsx("div",{className:"skel",style:{width:"72%",height:28,marginBottom:16}}),r.jsx("div",{className:"skel",style:{width:340,height:20,marginBottom:32}}),r.jsx("div",{className:"skel",style:{width:"100%",height:96,marginBottom:30}}),r.jsx("div",{className:"skel",style:{width:"100%",height:132,marginBottom:30}}),r.jsx("div",{className:"skel",style:{width:"100%",height:56}})]})})}function Qg({data:e,notice:t,onEdit:n}){const{spec:s,parent:l,children:o,links:a,childLinks:i}=e,c=l?.sourcePath??s.sourcePath??"",d=e.source!=null&&Dp(e.source,s.id)!=null,u=d?"Edit this requirement in place":e.source==null?"Source file not available":"Couldn’t locate this requirement’s section in the source file",f=o.filter(k=>k.kind==="acceptance"),h=k=>sl(i[k.id],"pending"),g=sl(a,"drafted"),v=f.filter(k=>Bg.has(h(k))).length,p=(fe[g]??fe.info).color,j=g==="verified"?Dr(a.reduce((k,C)=>Math.max(k,C.updatedAt??0),0)||void 0):null,m=g==="verified"?"var(--success)":g==="broken"||g==="drifted"||g==="orphaned"?"var(--warn)":"var(--text-secondary)",x=typeof s.metadata?.rationale=="string"?s.metadata.rationale:typeof s.rationale=="string"?s.rationale:null,y=k=>[k.targetFilePath,k.targetQualifiedName].filter(Boolean).join(":")||"—",w=k=>B("graph",{query:{focus:k.resolvedNodeId||"spec:"+s.id}}),S=r.jsx("span",{className:"sep"});return r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"28px 32px 56px"},children:r.jsxs("div",{className:"sp-doc",children:[t!=null&&r.jsxs("div",{className:"card card-pad row gap-8",style:{color:"var(--warn)",borderColor:"var(--warn)",marginBottom:20,fontSize:12.5},children:[r.jsx(z,{name:"drift",size:14,style:{flexShrink:0}}),r.jsxs("span",{children:["Saved, but not yet indexed — re-sync failed (",t,"). The file is on disk; the next sync picks it up."]})]}),r.jsxs("div",{className:"sp-breadcrumb",children:[r.jsx(z,{name:"book",size:13,style:{color:"var(--node-spec)",flexShrink:0}}),r.jsx("span",{className:"mono sp-path",style:{color:"var(--text-secondary)"},children:c}),r.jsx(z,{name:"chevronRight",size:11,style:{flexShrink:0}}),r.jsx("span",{className:"mono",style:{color:"var(--node-spec)",fontWeight:600,flexShrink:0},children:s.id}),r.jsx(pt,{text:s.id,ariaLabel:"Copy spec id"})]}),r.jsx("h1",{className:"sp-title",children:s.title}),r.jsxs("div",{className:"sp-metaline",style:{marginBottom:32},children:[r.jsx(Ge,{state:g,pulse:g==="broken"||g==="drifted"}),r.jsx(re,{children:s.priority||"—"}),S,r.jsx("span",{className:"fact",children:r.jsx("b",{children:s.kind||"requirement"})}),S,r.jsxs("span",{className:"fact",children:["owned by ",r.jsx("b",{className:"mono",children:s.owner||"—"})]}),S,r.jsxs("span",{className:"fact",children:[g==="verified"?"verified ":null,r.jsx("b",{style:{color:m},children:j?j+" ago":"—"})]})]}),r.jsxs("div",{className:"sp-sec",children:[r.jsx("div",{className:"sp-label",children:"Requirement"}),r.jsx("div",{className:"sp-statement lead",style:{"--sp-accent":p},children:s.body?.trim()?r.jsx("div",{className:"sp-prose",dangerouslySetInnerHTML:{__html:Rs(s.body)}}):r.jsx("div",{className:"muted",style:{fontSize:13},children:"No normative statement recorded."})})]}),x&&r.jsxs("div",{className:"sp-sec",children:[r.jsx("div",{className:"sp-label",children:"Why it matters"}),r.jsx("div",{className:"sp-rationale",dangerouslySetInnerHTML:{__html:Rs(x)}})]}),f.length>0&&r.jsxs("div",{className:"sp-sec",children:[r.jsxs("div",{className:"sp-label",children:["Acceptance criteria",r.jsx("span",{className:"ct tabular",style:{color:v===f.length?"var(--success)":"var(--text-muted)"},children:v+" / "+f.length+" met"})]}),r.jsx("div",{className:"row gap-4",style:{marginBottom:12},children:f.map(k=>{const C=h(k),_=fe[C]??fe.info;return r.jsx("div",{title:Fc(k.id)+" · "+Fg(C),style:{flex:1,height:4,borderRadius:999,background:_.color,opacity:C==="pending"?.25:.9}},k.id)})}),r.jsx("div",{className:"card",style:{overflow:"hidden"},children:f.map(k=>r.jsxs("div",{className:"sp-crit",children:[r.jsx($g,{state:h(k)}),r.jsx("span",{className:"sp-crit-id",children:Fc(k.id)}),r.jsx("span",{className:"sp-crit-text",dangerouslySetInnerHTML:{__html:Rs(k.body||k.title)}})]},k.id))})]}),r.jsxs("div",{className:"sp-sec",children:[r.jsxs("div",{className:"sp-label",children:["Linked code",a.length>0&&r.jsx("span",{className:"ct",children:a.length+(a.length===1?" symbol":" symbols")})]}),a.length?r.jsx("div",{className:"card",style:{overflow:"hidden"},children:a.map((k,C)=>r.jsxs("div",{className:"row gap-10",style:{padding:"11px 14px",borderTop:C?"1px solid var(--border-subtle)":"none"},children:[r.jsx(Ge,{state:k.state}),k.driftAxis&&r.jsx(re,{color:"var(--warn)",bg:"var(--warn-soft)",children:k.driftAxis+" drift"}),r.jsx("span",{className:"mono grow",style:{fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:y(k)}),r.jsx(re,{children:k.provenance||"—"}),r.jsxs("button",{className:"btn btn-ghost btn-xs",onClick:()=>w(k),title:"Reveal in the graph",children:[r.jsx(z,{name:"reveal",size:12}),"Reveal"]})]},C))}):r.jsxs("div",{className:"card card-pad",style:{textAlign:"center",color:"var(--error)",borderColor:"rgba(242,85,90,0.3)"},children:[r.jsx(z,{name:"drift",size:16}),r.jsx("div",{style:{marginTop:6,fontSize:12.5},children:"Orphaned — no code implements this requirement yet"})]})]}),r.jsxs("div",{className:"row gap-8",style:{flexWrap:"wrap",marginTop:4},children:[r.jsxs("button",{className:"btn btn-primary btn-sm",disabled:!0,title:"Run automatically by the implementation workflow once Drafted",children:[r.jsx(z,{name:"play",size:13}),"Implement"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",disabled:!0,title:"Run automatically by the verification workflow",children:[r.jsx(z,{name:"check",size:13}),"Verify"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",disabled:!d,title:u,onClick:d?n:void 0,children:[r.jsx(z,{name:"reveal",size:13}),"Edit spec"]}),r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>B("graph",{query:{focus:"spec:"+s.id}}),children:[r.jsx(z,{name:"graph",size:13}),"Show in graph"]})]})]})})}const Yg=["pending","implementing","implemented","verified","drifted","broken"],Gg=["P0","P1","P2","P3"],qg=["requirement","constraint","guideline","invariant","non-functional"];function Xg(e,t){const{spec:n,childLinks:s}=e,l=typeof n.metadata?.rationale=="string"?n.metadata.rationale:typeof n.rationale=="string"?n.rationale:"";return{title:t.title,priority:n.priority??"",kind:n.kind??"requirement",owner:n.owner??"",statement:t.statement,rationale:l,criteria:t.criteria.map(o=>({id:o.id,state:sl(s[o.id],"pending"),text:o.text}))}}const Jg={title:"",priority:"",kind:"requirement",owner:"",statement:"",rationale:"",criteria:[]};function mn({label:e,hint:t,children:n}){return r.jsxs("div",{style:{marginBottom:22},children:[r.jsx("label",{className:"sp-fl",children:e}),n,t&&r.jsx("div",{className:"muted",style:{fontSize:11,marginTop:6},children:t})]})}function Zg({value:e,onChange:t,options:n,label:s}){const l=n.includes(e)?n:[e,...n];return r.jsx("select",{className:"input sp-select","aria-label":s,value:e,onChange:o=>t(o.target.value),style:{width:"100%",textTransform:"capitalize"},children:l.map(o=>r.jsx("option",{value:o,children:o},o))})}function ev({value:e,onChange:t,options:n,width:s,label:l}){const o=fe[e]??fe.info;return r.jsxs("div",{className:"row",style:{position:"relative",width:s??"auto",flexShrink:0},children:[r.jsx("span",{className:"pill-dot","data-testid":"crit-state-dot",style:{background:o.color,position:"absolute",left:11,pointerEvents:"none",zIndex:1}}),r.jsx("select",{className:"input sp-select","aria-label":l,value:e,onChange:a=>t(a.target.value),style:{width:"100%",paddingLeft:26,textTransform:"capitalize"},children:n.map(a=>r.jsx("option",{value:a,children:fe[a]?.label??a},a))})]})}function tv({state:e}){return r.jsxs("div",{className:"sp-status-auto",children:[e==="drafted"?r.jsxs(r.Fragment,{children:[r.jsx(Ge,{state:"drafted"}),r.jsx("span",{className:"muted",style:{fontSize:12},children:"queued for implementation"})]}):r.jsxs(r.Fragment,{children:[r.jsx(Ge,{state:e}),r.jsx(z,{name:"arrowRight",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx(Ge,{state:"drafted"})]}),r.jsx("span",{className:"grow"}),r.jsx(z,{name:"lock",size:12,style:{color:"var(--text-faint)",flexShrink:0}})]})}function nv({criteria:e,onChange:t}){const n=(s,l)=>t(e.map((o,a)=>a===s?{...o,...l}:o));return r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"row",style:{marginBottom:10,gap:10},children:[r.jsx("span",{className:"eyebrow",children:"Acceptance criteria"}),r.jsx("span",{style:{flex:1,height:1,background:"var(--border-subtle)"}}),r.jsx("span",{className:"mono tabular muted",style:{fontSize:11.5},children:e.length+" total"})]}),r.jsx("div",{className:"card",style:{overflow:"hidden",marginBottom:12},children:e.length===0?r.jsx("div",{className:"muted",style:{fontSize:12.5,textAlign:"center",padding:"18px 14px"},children:"No criteria yet — add one below."}):e.map((s,l)=>r.jsxs("div",{className:"sp-crit-edit",children:[r.jsx("span",{className:"sp-crit-grip",children:r.jsx(z,{name:"grip",size:14})}),r.jsx("span",{className:"sp-crit-num",children:"A"+(l+1)}),r.jsx(ev,{value:s.state,onChange:o=>n(l,{state:o}),options:Yg,width:156,label:"Criterion A"+(l+1)+" state"}),r.jsx("input",{className:"input grow",style:{fontSize:13},value:s.text,"aria-label":"Criterion A"+(l+1)+" text",placeholder:"Observable, testable condition…",onChange:o=>n(l,{text:o.target.value})}),r.jsx("button",{className:"sp-icon-btn",title:"Remove criterion","aria-label":"Remove criterion A"+(l+1),onClick:()=>t(e.filter((o,a)=>a!==l)),children:r.jsx(z,{name:"trash",size:14})})]},l))}),r.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>t([...e,{id:"",state:"pending",text:""}]),children:[r.jsx(z,{name:"plus",size:13}),"Add criterion"]})]})}function rv({data:e,project:t,onCancel:n,onSaved:s}){const{spec:l}=e,o=e.parent?.sourcePath??l.sourcePath??"",a=N.useMemo(()=>Dp(e.source??"",l.id),[e.source,l.id]),[i,c]=N.useState(()=>a?Xg(e,a):Jg),d=N.useRef(JSON.stringify(i)),u=JSON.stringify(i)!==d.current,[f,h]=N.useState("write"),[g,v]=N.useState(!1),[p,j]=N.useState(null),m=k=>c(C=>({...C,...k})),x=sl(e.links,"drafted"),y=(fe[x]??fe.info).color;if(!a)return r.jsx(ue,{icon:"drift",title:"Can’t edit this spec",body:"Its requirement section couldn’t be located in the source file."});const w=async()=>{if(!u||g)return;const k=Ig({title:i.title,statement:i.statement,criteria:i.criteria}),C=Ag(e.source??"",l.id,k);if(C===null){j("Could not locate this requirement’s section in the source file.");return}v(!0),j(null);try{const _=await P.specSave(l.id,C,t);s(_.syncError??null)}catch(_){j(_ instanceof Error?_.message:String(_)),v(!1)}},S=r.jsxs("button",{className:"btn btn-primary btn-sm",disabled:!u||g,onClick:w,children:[r.jsx(z,{name:"check",size:13}),g?"Saving…":"Save changes"]});return r.jsxs("div",{className:"col",style:{flex:1,minHeight:0},children:[r.jsxs("div",{className:"sp-edit-bar",children:[r.jsx(z,{name:"reveal",size:15,style:{color:"var(--accent)",flexShrink:0}}),r.jsxs("div",{className:"col",style:{gap:1,minWidth:0},children:[r.jsx("div",{style:{fontSize:13,fontWeight:600},children:"Editing spec"}),r.jsx("div",{className:"mono muted",style:{fontSize:11,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:o+" · "+l.id})]}),r.jsx("div",{className:"grow"}),u&&r.jsxs("div",{className:"row gap-6",style:{marginRight:4},children:[r.jsx("span",{className:"sp-dirty-dot"}),r.jsx("span",{className:"muted",style:{fontSize:11.5},children:"Unsaved changes"})]}),r.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:n,children:[r.jsx(z,{name:"x",size:13}),"Cancel"]}),S]}),r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"24px 28px 56px"},children:r.jsxs("div",{style:{maxWidth:780},children:[p&&r.jsxs("div",{className:"card card-pad row gap-8",role:"alert",style:{color:"var(--error)",borderColor:"rgba(242,85,90,0.35)",marginBottom:18,fontSize:12.5},children:[r.jsx(z,{name:"cancel",size:14,style:{flexShrink:0}}),r.jsxs("span",{children:["Save failed — ",p," Your draft is intact."]})]}),r.jsx(mn,{label:"Title",children:r.jsx("input",{className:"input sp-input-lg",value:i.title,"aria-label":"Title",placeholder:"Short, imperative requirement title",onChange:k=>m({title:k.target.value})})}),r.jsxs("div",{className:"sp-edit-grid",children:[r.jsx(mn,{label:"Status",hint:"Set automatically — saving re-queues this spec as Drafted so the implementation workflow picks it up.",children:r.jsx(tv,{state:x})}),r.jsx(mn,{label:"Priority",children:r.jsx(Ce,{options:Gg,value:i.priority,onChange:k=>m({priority:k}),label:"Priority"})}),r.jsx(mn,{label:"Kind",children:r.jsx(Zg,{value:i.kind,onChange:k=>m({kind:k}),options:qg,label:"Kind"})}),r.jsx(mn,{label:"Owner",children:r.jsx("input",{className:"input mono",style:{width:"100%"},value:i.owner,"aria-label":"Owner",placeholder:"unassigned",onChange:k=>m({owner:k.target.value})})})]}),r.jsx("div",{className:"muted",style:{fontSize:11,margin:"-8px 0 22px"},children:"Priority, kind, and owner are document-level in the current spec format — they render from available data but aren’t persisted per-requirement yet."}),r.jsxs("div",{style:{marginBottom:22},children:[r.jsxs("div",{className:"row",style:{marginBottom:7},children:[r.jsx("label",{className:"sp-fl",style:{marginBottom:0},children:"Normative statement"}),r.jsx("div",{className:"grow"}),r.jsx(Ce,{size:"sm",options:[{value:"write",label:"Write"},{value:"preview",label:"Preview"}],value:f,onChange:h,label:"Statement editor mode"})]}),f==="write"?r.jsx("textarea",{className:"input sp-textarea",value:i.statement,spellCheck:!1,"aria-label":"Normative statement",placeholder:"The server MUST validate … (use MUST / SHOULD / MAY, **bold**, and `code`)",onChange:k=>m({statement:k.target.value})}):r.jsx("div",{className:"sp-statement",style:{"--sp-accent":y},children:i.statement.trim()?r.jsx("div",{className:"sp-prose",dangerouslySetInnerHTML:{__html:Rs(i.statement)}}):r.jsx("div",{className:"muted",style:{fontSize:13},children:"Nothing to preview yet."})}),r.jsxs("div",{className:"sp-kw-legend",children:[r.jsx("span",{className:"label",children:"Keywords:"}),r.jsx("span",{className:"sp-kw sp-kw-must",children:"MUST"}),r.jsx("span",{className:"sp-kw sp-kw-should",children:"SHOULD"}),r.jsx("span",{className:"sp-kw sp-kw-may",children:"MAY"}),r.jsx("span",{className:"label",style:{marginLeft:4},children:"auto-highlight as you type"})]})]}),r.jsx(mn,{label:"Rationale",hint:"Optional — why this requirement exists. Presentation-only today: the spec format carries no per-requirement rationale field.",children:r.jsx("textarea",{className:"input sp-textarea",value:i.rationale,spellCheck:!1,style:{minHeight:84},"aria-label":"Rationale",placeholder:"Why does this matter? What breaks without it?",onChange:k=>m({rationale:k.target.value})})}),r.jsx(nv,{criteria:i.criteria,onChange:k=>m({criteria:k})}),r.jsxs("div",{className:"row",style:{gap:10,marginTop:32,paddingTop:20,borderTop:"1px solid var(--border-subtle)"},children:[S,r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:n,children:"Cancel"}),r.jsx("div",{className:"grow"}),r.jsx("span",{className:"mono muted",style:{fontSize:11},children:u?"edited":"no changes"})]})]})})]})}function Hc(e){return t=>{(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),e())}}function sv(e){const t=new Map,n=new Map(e.map(l=>[l.id,l])),s=(l,o)=>{let a=t.get(l);return a||(a={doc:o,path:l,reqs:[]},t.set(l,a)),o&&!a.doc&&(a.doc=o),a};for(const l of e)l.kind==="document"&&s(l.sourcePath??l.id,l);for(const l of e){if(l.kind!=="requirement")continue;const o=l.parentId?n.get(l.parentId):void 0,a=o?.sourcePath??l.sourcePath??"(unknown)";s(a,o?.kind==="document"?o:null).reqs.push(l)}return[...t.values()]}const lv=["verified","implemented","drifted","broken","orphaned"];function ov({project:e,param:t,query:n}){const s=L(()=>P.specs(e),[e]),[l,o]=N.useState(t??n.sel??null);N.useEffect(()=>{const p=t??n.sel;p&&o(p)},[t,n.sel]);const[a,i]=N.useState(new Set),c=N.useRef(new Map).current,d=N.useMemo(()=>sv(s.data?.specs??[]),[s.data]),u=s.data?.linkStates??{};if(Kt(s.error))return r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."});const f=d.reduce((p,j)=>p+j.reqs.length,0),h={};for(const p of d)for(const j of p.reqs){const m=u[j.id];m&&(h[m]=(h[m]??0)+1)}const g=p=>{const j=u[p.id];return!!j&&a.has(j)},v=p=>i(j=>{const m=new Set(j);return m.has(p)?m.delete(p):m.add(p),m});return r.jsxs("div",{style:{flex:1,display:"flex",minHeight:0},children:[r.jsxs("div",{className:"col",style:{width:280,flexShrink:0,borderRight:"1px solid var(--border-subtle)",background:"var(--bg-panel)"},children:[r.jsxs("div",{className:"row",style:{gap:8,padding:"11px 12px",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"book",size:15,style:{color:"var(--accent)"}}),r.jsx("span",{style:{fontWeight:600,fontSize:13},children:"Specs"}),r.jsx("span",{className:"grow"}),r.jsx("span",{className:"muted tabular",style:{fontSize:11},children:s.data?f+" reqs":"…"})]}),r.jsxs("div",{className:"row",style:{gap:5,padding:"8px 10px",flexWrap:"wrap",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"filter",size:12,style:{color:"var(--text-muted)",flexShrink:0}}),lv.map(p=>{const j=!a.has(p),m=fe[p];return r.jsxs("button",{onClick:()=>v(p),className:"row gap-4",style:{height:22,padding:"0 8px",borderRadius:999,fontSize:10.5,fontWeight:500,cursor:"pointer",textTransform:"capitalize",border:"1px solid "+(j?"transparent":"var(--border-subtle)"),background:j?m.bg:"var(--bg-panel)",color:j?m.color:"var(--text-muted)"},children:[p,r.jsx("span",{className:"tabular",style:{opacity:.7},children:h[p]??0})]},p)})]}),r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:6},role:d.length?"tree":void 0,"aria-label":d.length?"Spec tree":void 0,children:[s.data&&!d.length&&r.jsx(ue,{icon:"book",title:"No specs yet",body:"Author one with the spec-author skill — specs/*.md index on sync."}),d.map(p=>r.jsx(av,{group:p,linkStates:u,selId:l,hidden:g,onSel:o},p.path))]})]}),r.jsx("div",{className:"col",style:{flex:1,minWidth:0},children:r.jsx(Hg,{id:l,project:e,cache:c},l??"")})]})}function av({group:e,linkStates:t,selId:n,hidden:s,onSel:l}){const[o,a]=N.useState(!0),i=e.reqs.filter(d=>!s(d)),c=e.reqs.filter(d=>["drifted","broken","orphaned"].includes(t[d.id]??"")).length;return r.jsxs("div",{children:[r.jsxs("div",{onClick:()=>a(!o),onKeyDown:Hc(()=>a(!o)),role:"treeitem","aria-expanded":o,tabIndex:0,className:"row gap-6 list-row",style:{padding:"6px 8px",borderRadius:6,cursor:"pointer",color:"var(--text-secondary)"},children:[r.jsx(z,{name:o?"chevronDown":"chevronRight",size:12,style:{color:"var(--text-muted)"}}),r.jsx(z,{name:"book",size:13,style:{color:"var(--node-spec)"}}),r.jsx("span",{className:"mono grow",style:{fontSize:12,color:"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.path.replace(/^specs\//,"")}),c>0&&r.jsx("span",{className:"pill",style:{fontSize:9.5,color:"var(--warn)",background:"var(--warn-soft)"},children:c})]}),o&&i.length>0&&r.jsx("div",{role:"group",style:{marginLeft:14,borderLeft:"1px solid var(--border-subtle)",paddingLeft:6},children:i.map(d=>{const u=n===d.id,f=fe[t[d.id]??""]??fe.drafted;return r.jsxs("div",{onClick:()=>l(d.id),onKeyDown:Hc(()=>l(d.id)),role:"treeitem","aria-selected":u,tabIndex:0,className:"row gap-6 list-row"+(u?" selected":""),style:{padding:"5px 8px",borderRadius:6,cursor:"pointer"},children:[r.jsx("span",{className:"pill-dot",style:{background:f.color,flexShrink:0}}),r.jsxs("div",{className:"grow",style:{minWidth:0},children:[r.jsx("div",{className:"mono",style:{fontSize:11,color:u?"var(--accent)":"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.id}),r.jsx("div",{className:"muted",style:{fontSize:10.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.title})]})]},d.id)})})]})}const Uc={error:0,warn:1,info:2},iv=e=>e==="error"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)";function cv({query:e,tips:t,onSetTipState:n}){const s=L(()=>P.claudeStats(),[]),l=s.data?.sessionCount===0,o=e.sel,a=t.data?.tips??[],i=[...a].sort((d,u)=>(Uc[d.severity]??9)-(Uc[u.severity]??9)),c=d=>a.filter(u=>u.severity===d&&u.state!=="applied").length;return r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:18},children:[r.jsx(Ae,{icon:"tips",title:"Tips",sub:"A senior teammate reviewed your transcripts",actions:a.length>0&&r.jsxs("div",{className:"row gap-6",children:[r.jsxs(re,{color:"var(--error)",bg:"var(--error-soft)",children:[c("error")," urgent"]}),r.jsxs(re,{color:"var(--warn)",bg:"var(--warn-soft)",children:[c("warn")," warn"]}),r.jsxs(re,{color:"var(--info)",bg:"var(--info-soft)",children:[c("info")," info"]})]})}),l&&!a.length?r.jsx(Fn,{onIngested:()=>{s.reload(),t.reload()}}):r.jsx(ae,{state:t,label:"tips",minHeight:240,children:d=>d.tips.length?r.jsx("div",{className:"col gap-12",style:{maxWidth:860},children:i.map(u=>r.jsx(dv,{tip:u,focus:u.id===o,onApply:()=>n(u.id,"applied"),onDismiss:()=>n(u.id,"dismissed")},u.id))}):r.jsx("div",{className:"muted",style:{fontSize:12.5,padding:8},children:"No tips — nothing wasteful in your recent sessions."})})]})}function dv({tip:e,focus:t,onApply:n,onDismiss:s}){const[l,o]=N.useState(!1),a=N.useRef(null);N.useEffect(()=>{if(!t||!a.current)return;const d=a.current,u=d.closest(".scroll-y");u&&(u.scrollTop=Math.max(0,d.offsetTop-20)),o(!0);const f=setTimeout(()=>o(!1),1800);return()=>clearTimeout(f)},[t]);const i=iv(e.severity),c=e.state==="applied";return r.jsxs("div",{ref:a,className:"card",style:{display:"flex",opacity:c?.7:1,transition:"box-shadow var(--motion-fast), border-color var(--motion-fast)",boxShadow:l?`0 0 0 2px ${i}`:"none",borderColor:l?i:void 0},children:[r.jsx("div",{style:{width:3,background:i,flexShrink:0,borderRadius:"9px 0 0 9px"}}),r.jsxs("div",{style:{padding:"14px 16px",flex:1,minWidth:0},children:[r.jsxs("div",{className:"row gap-10",style:{marginBottom:10},children:[r.jsx("div",{style:{width:28,height:28,borderRadius:8,background:`color-mix(in srgb, ${i} 16%, transparent)`,display:"grid",placeItems:"center",color:i,flexShrink:0},children:r.jsx(z,{name:e.icon,size:15})}),r.jsx("div",{className:"grow",style:{minWidth:0},children:r.jsx("div",{style:{fontSize:14,fontWeight:600,letterSpacing:"-0.01em",textWrap:"pretty"},children:e.title})}),r.jsx(re,{color:i,bg:`color-mix(in srgb, ${i} 14%, transparent)`,children:e.severity})]}),r.jsx("div",{className:"secondary",style:{fontSize:12.5,lineHeight:1.6,marginBottom:12},children:e.why}),r.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:14},children:[r.jsxs("div",{onClick:()=>B("sessions",{query:{sel:e.evidence.session}}),role:"button",tabIndex:0,onKeyDown:d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),B("sessions",{query:{sel:e.evidence.session}}))},title:"Open session "+e.evidence.session,className:"list-row",style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:8,padding:10,cursor:"pointer"},children:[r.jsxs("div",{className:"row gap-6",style:{marginBottom:5},children:[r.jsx("span",{className:"eyebrow",children:"Evidence"}),r.jsx("span",{className:"grow"}),r.jsx(z,{name:"arrowRight",size:11,style:{color:"var(--text-muted)"}})]}),r.jsxs("div",{className:"row gap-6",style:{fontSize:11.5},children:[r.jsx(z,{name:"sessions",size:11,style:{color:"var(--text-muted)"}}),r.jsx("span",{className:"mono",style:{color:"var(--accent)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.evidence.session})]}),r.jsx("div",{className:"mono secondary",style:{fontSize:11,marginTop:4,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.evidence.detail})]}),r.jsxs("div",{style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:8,padding:10},children:[r.jsx("div",{className:"eyebrow",style:{marginBottom:5},children:"Impact"}),r.jsx("div",{className:"tabular",style:{fontSize:16,fontWeight:700,color:"var(--success)"},children:e.saving})]})]}),r.jsxs("div",{className:"row gap-8",style:{alignItems:"center"},children:[r.jsxs("div",{className:"row gap-8 grow",style:{background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:7,padding:"6px 10px",minWidth:0},children:[r.jsx("span",{className:"muted",style:{fontSize:10.5,flexShrink:0},children:"fix"}),r.jsx("code",{className:"mono grow",style:{fontSize:11.5,color:"var(--text-primary)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.fix}),r.jsx(pt,{text:e.fix})]}),c?r.jsxs("span",{className:"pill",style:{color:"var(--success)",background:"var(--success-soft)"},children:[r.jsx(z,{name:"check",size:11}),"Applied"]}):r.jsx("button",{className:"btn btn-primary btn-sm",onClick:n,title:"Mark applied",children:"Apply"}),r.jsx("button",{className:"btn btn-secondary btn-sm",onClick:s,title:"Dismiss — this tip won't come back",children:"Dismiss"})]})]})]})}const uv={bundled:"var(--node-spec)",global:"var(--node-code)",project:"var(--node-route)"};function pv({project:e,query:t}){const n=L(()=>P.workflows(e),[e]),s=n.data?.workflows??[],[l,o]=N.useState(t.run??null);if(Kt(n.error))return r.jsx(ue,{icon:"folder",title:"No project selected",body:"Pick an indexed project from the switcher in the status strip."});const a=l?s.find(i=>i.workflow.name===l):void 0;return r.jsxs("div",{className:"scroll-y",style:{flex:1,padding:18},children:[r.jsx(Ae,{icon:"workflow",title:"Workflows",sub:n.data?"Run a YAML-defined DAG of agent, shell and approval steps":"Loading workflows…"}),n.data&&!s.length&&r.jsx(ue,{icon:"workflow",title:"No workflows found",body:"Add YAML definitions under .specship/workflows/ in this project or your home directory."}),r.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(340px, 1fr))",gap:12},children:s.map(({workflow:i,scope:c})=>{const d=uv[c]??"var(--text-secondary)";return r.jsxs("div",{className:"card card-pad",style:{display:"flex",flexDirection:"column",gap:10},children:[r.jsxs("div",{className:"row gap-8",children:[r.jsx("span",{className:"mono",style:{fontSize:13.5,fontWeight:600},children:i.name}),r.jsx(re,{color:d,bg:`color-mix(in srgb, ${d} 14%, transparent)`,children:c}),r.jsx("span",{className:"grow"}),r.jsxs("span",{className:"mono muted tabular",style:{fontSize:10.5},children:[i.nodes.length," nodes"]})]}),r.jsx("div",{className:"secondary",style:{fontSize:12.5,lineHeight:1.5,minHeight:36},children:i.description||"No description."}),r.jsxs("div",{className:"row gap-6",style:{flexWrap:"wrap",borderTop:"1px solid var(--border-subtle)",paddingTop:10},children:[(i.requires??[]).length>0&&r.jsx("span",{className:"muted",style:{fontSize:10.5},children:"requires"}),(i.requires??[]).map(u=>r.jsx("code",{className:"mono",style:{fontSize:10.5,color:"var(--text-secondary)",background:"var(--bg-canvas)",padding:"1px 6px",borderRadius:4},children:u},u)),(i.inputs??[]).length>0&&r.jsxs(r.Fragment,{children:[r.jsx("span",{className:"muted",style:{fontSize:10.5,marginLeft:6},children:"inputs"}),(i.inputs??[]).map(u=>r.jsxs("code",{className:"mono",style:{fontSize:10.5,color:"var(--node-spec)",background:"var(--node-spec-soft)",padding:"1px 6px",borderRadius:4},children:["$",u.name]},u.name))]}),r.jsx("span",{className:"grow"}),r.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>o(i.name),children:[r.jsx(z,{name:"play",size:13}),"Launch"]})]})]},i.name)})}),a&&r.jsx(fv,{wf:a.workflow,project:e,onClose:()=>o(null)})]})}function fv({wf:e,project:t,onClose:n}){const s=e.inputs??[],[l,o]=N.useState(()=>Object.fromEntries(s.filter(h=>h.default).map(h=>[h.name,h.default]))),[a,i]=N.useState(!1),[c,d]=N.useState(null),u=s.filter(h=>h.required&&!(l[h.name]??"").trim()),f=()=>{if(a||u.length)return;i(!0),d(null);const h=Object.fromEntries(Object.entries(l).filter(([,g])=>g.trim()));P.launchRun(e.name,h,t).then(g=>B("runs",{param:g.runId}),g=>{d(g instanceof Error?g.message:String(g)),i(!1)})};return r.jsx("div",{onMouseDown:n,role:"dialog","aria-label":"Launch "+e.name,style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.5)",zIndex:90,display:"grid",placeItems:"center"},children:r.jsxs("div",{onMouseDown:h=>h.stopPropagation(),style:{width:460,maxWidth:"90vw",background:"var(--bg-elevated)",border:"1px solid var(--border-strong)",borderRadius:12,boxShadow:"var(--shadow-pop)"},children:[r.jsxs("div",{className:"row gap-10",style:{padding:"14px 16px",borderBottom:"1px solid var(--border-subtle)"},children:[r.jsx(z,{name:"workflow",size:16,style:{color:"var(--accent)"}}),r.jsx("span",{className:"mono grow",style:{fontWeight:600},children:e.name}),r.jsx("button",{className:"btn btn-ghost btn-xs",onClick:n,"aria-label":"Close",children:r.jsx(z,{name:"x",size:14})})]}),r.jsxs("div",{style:{padding:16},children:[r.jsx("div",{className:"secondary",style:{fontSize:12.5,marginBottom:16,lineHeight:1.55},children:e.description||"No description."}),s.length?s.map(h=>r.jsxs("div",{style:{marginBottom:12},children:[r.jsxs("label",{className:"eyebrow",style:{display:"block",marginBottom:5},htmlFor:"wf-input-"+h.name,children:[h.name,h.required&&r.jsx("span",{style:{color:"var(--error)"},children:" *"})]}),r.jsx("input",{id:"wf-input-"+h.name,className:"input mono",style:{width:"100%"},placeholder:h.description||(h.name==="SPEC_ID"?"REQ-AUTH-005":"value…"),value:l[h.name]||"",onChange:g=>o(v=>({...v,[h.name]:g.target.value})),onKeyDown:g=>{g.key==="Enter"&&f()}})]},h.name)):r.jsx("div",{className:"muted",style:{fontSize:12,padding:"8px 0"},children:"No inputs required."}),r.jsx("div",{className:"row gap-6",style:{marginTop:6,marginBottom:4},children:(e.requires??[]).map(h=>r.jsxs(re,{children:[r.jsx(z,{name:"check",size:10}),h]},h))}),c&&r.jsxs("div",{className:"row gap-8",style:{marginTop:8,padding:"8px 10px",borderRadius:7,background:"var(--error-soft)",color:"var(--error)",fontSize:12},children:[r.jsx(z,{name:"cancel",size:13,style:{flexShrink:0}}),r.jsx("span",{children:c})]})]}),r.jsxs("div",{className:"row gap-8",style:{padding:"12px 16px",borderTop:"1px solid var(--border-subtle)",justifyContent:"flex-end"},children:[r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:n,children:"Cancel"}),r.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,disabled:a||u.length>0,title:u.length?"Fill the required inputs: "+u.map(h=>h.name).join(", "):void 0,children:[r.jsx(z,{name:"play",size:13}),a?"Launching…":"Launch run"]})]})]})})}const xi=[{group:"Project",items:[{id:"dashboard",label:"Dashboard",icon:"dashboard"},{id:"graph",label:"Graph",icon:"graph"},{id:"specs",label:"Specs",icon:"book"},{id:"drift",label:"Drift queue",icon:"drift",badge:e=>e.drift},{id:"runs",label:"Runs",icon:"play",badge:e=>e.runs,badgeKind:"warn"}]},{group:"Claude Code",items:[{id:"sessions",label:"Sessions",icon:"sessions"},{id:"heatmap",label:"Heatmap",icon:"heatmap"},{id:"costs",label:"Costs",icon:"dollar"},{id:"compare",label:"Compare projects",icon:"compare"},{id:"memory",label:"Memory",icon:"memory"},{id:"mcp",label:"MCP",icon:"plug"},{id:"tips",label:"Tips",icon:"tips",badge:e=>e.tips,badgeKind:"error"}]}],hv=[...xi.flatMap(e=>e.items.map(({id:t,label:n,icon:s})=>({id:t,label:n,icon:s}))),{id:"workflows",label:"Workflows",icon:"workflow"},{id:"chat",label:"Chat",icon:"chat"},{id:"designsystem",label:"Design system",icon:"layers"},{id:"settings",label:"Settings",icon:"settings"}],mv=xi.flatMap(e=>e.items.map(t=>t.id)).slice(0,7),xv={dashboard:dx,graph:Ax,specs:ov,drift:Rx,runs:Sg,workflows:pv,chat:$m,designsystem:()=>r.jsx(Tx,{}),sessions:Ng,heatmap:Bx,costs:ax,compare:sx,memory:ag,mcp:eg,settings:e=>r.jsx(Og,{...e})},co="ss_project",Vc="ss_nav_groups",Kc="ss_nav_collapsed";function gv(){const{route:e,param:t,query:n}=hm(),[s,l]=N.useState(()=>{try{return localStorage.getItem(Kc)==="1"}catch{return!1}}),[o,a]=N.useState(()=>{try{return localStorage.getItem(co)}catch{return null}}),[i,c]=N.useState(!1),[d,u]=N.useState(!1),f=L(()=>P.status(o),[o,e]),h=L(()=>P.projects(),[]),g=L(()=>P.runs(o),[o,e]),v=L(()=>P.claudeTips(),[e]),p=L(()=>P.drift(o),[o,e]),j=N.useCallback(()=>u(_=>!_),[]);Cm({onTogglePalette:j,pageIds:mv});const m={drift:p.data?.links.length??f.data?.drift??0,runs:g.data?.runs.filter(_=>_.status==="running").length??0,tips:v.data?.tips.filter(_=>_.state!=="applied").length??0},x=N.useCallback(()=>u(!0),[]),y=N.useCallback((_,W)=>{P.setTipState(_,W).catch(()=>{}).finally(()=>v.reload())},[v.reload]),w=()=>l(_=>{try{localStorage.setItem(Kc,_?"0":"1")}catch{}return!_}),S=_=>{a(_);try{_?localStorage.setItem(co,_):localStorage.removeItem(co)}catch{}},k=()=>{c(!0),P.refresh(o).catch(()=>{}).finally(()=>{c(!1),f.reload()})},C=xv[e]??(()=>r.jsx(ig,{title:"Not found"}));return r.jsxs("div",{style:{display:"flex",height:"100%",position:"relative"},children:[r.jsx(vv,{route:e,collapsed:s,counts:m,version:f.data?.version,onToggleCollapse:w}),r.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",minWidth:0},children:[r.jsx(jv,{status:f.data,projectless:Kt(f.error),projects:h.data?.projects??[],project:o,onPick:S,onRefresh:k,refreshing:i}),r.jsx(Sv,{onToggle:w,onOpenPalette:x}),r.jsx("div",{"data-screen":e,style:{flex:1,minHeight:0,display:"flex",flexDirection:"column"},children:e==="tips"?r.jsx(cv,{project:o,param:t,query:n,tips:v,onSetTipState:y}):r.jsx(C,{project:o,param:t,query:n})},e+(t??""))]}),r.jsx(Sm,{open:d,onClose:()=>u(!1),pages:hv,project:o})]})}function vv({route:e,collapsed:t,counts:n,version:s,onToggleCollapse:l}){const[o,a]=N.useState(()=>{try{return JSON.parse(localStorage.getItem(Vc)||"null")||{}}catch{return{}}}),i=d=>o[d]!==!1,c=d=>a(u=>{const f={...u,[d]:u[d]===!1};try{localStorage.setItem(Vc,JSON.stringify(f))}catch{}return f});return r.jsxs("nav",{style:{width:t?"var(--sidebar-w-collapsed)":"var(--sidebar-w)",flexShrink:0,background:"var(--bg-panel)",borderRight:"1px solid var(--border-subtle)",display:"flex",flexDirection:"column",transition:"width 120ms",overflow:"hidden"},children:[r.jsxs("div",{className:"row gap-8",onClick:l,title:t?"Expand menu":"Collapse menu",style:{padding:t?"14px 0":"15px 16px",justifyContent:t?"center":"flex-start",cursor:"pointer",userSelect:"none"},children:[r.jsx(ap,{size:26}),!t&&r.jsx("div",{className:"grow",style:{fontWeight:600,fontSize:13.5,letterSpacing:"-0.01em"},children:"SpecShip"})]}),r.jsx("div",{className:"scroll-y",style:{flex:1,padding:"4px 8px"},children:xi.map(d=>r.jsxs("div",{style:{marginBottom:t?10:4},children:[!t&&r.jsxs("button",{onClick:()=>c(d.group),className:"row gap-6",style:{width:"100%",padding:"8px 8px 4px",background:"none",border:"none",cursor:"pointer",textAlign:"left"},children:[r.jsx("span",{className:"eyebrow grow",children:d.group}),r.jsx(z,{name:i(d.group)?"chevronDown":"chevronRight",size:12,style:{color:"var(--text-muted)"}})]}),(t||i(d.group))&&d.items.map(u=>r.jsx(uo,{item:u,active:e===u.id,collapsed:t,counts:n},u.id))]},d.group))}),r.jsxs("div",{style:{padding:8,borderTop:"1px solid var(--border-subtle)"},children:[r.jsx(uo,{item:{id:"designsystem",label:"Design system",icon:"layers"},active:e==="designsystem",collapsed:t}),r.jsx(uo,{item:{id:"settings",label:"Settings",icon:"settings"},active:e==="settings",collapsed:t}),s&&r.jsx("div",{className:"mono tabular",title:`SpecShip v${s}`,"data-testid":"app-version",style:{padding:t?"6px 0 2px":"6px 10px 2px",fontSize:10.5,color:"var(--text-muted)",textAlign:t?"center":"left",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},children:t?s:`v${s}`})]})]})}function uo({item:e,active:t,collapsed:n,counts:s}){const l=i=>{i.metaKey||i.ctrlKey||i.shiftKey||i.button!==0||(i.preventDefault(),B(e.id))},o=e.badge&&s?e.badge(s):0,a=e.badgeKind;return r.jsxs("a",{href:"/"+e.id,onClick:l,title:n?e.label:void 0,className:"list-row",style:{display:"flex",alignItems:"center",gap:10,height:32,padding:n?0:"0 10px",justifyContent:n?"center":"flex-start",borderRadius:7,textDecoration:"none",marginBottom:1,color:t?"var(--text-primary)":"var(--text-secondary)",background:t?"var(--bg-active)":void 0,fontWeight:t?600:450,fontSize:13,position:"relative"},children:[t&&r.jsx("span",{style:{position:"absolute",left:0,top:7,bottom:7,width:2.5,borderRadius:2,background:"var(--accent)"}}),r.jsx(z,{name:e.icon,size:16,style:{color:t?"var(--accent)":"inherit",flexShrink:0}}),!n&&r.jsx("span",{className:"grow",style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.label}),!n&&o>0&&r.jsx("span",{className:"pill tabular",style:{fontSize:10,fontWeight:700,padding:"1px 6px",minWidth:18,justifyContent:"center",color:a==="error"?"var(--error)":a==="warn"?"var(--warn)":"var(--text-secondary)",background:a==="error"?"var(--error-soft)":a==="warn"?"var(--warn-soft)":"rgba(255,255,255,0.06)"},children:o}),n&&o>0&&r.jsx("span",{style:{position:"absolute",top:5,right:9,width:6,height:6,borderRadius:"50%",background:a==="error"?"var(--error)":"var(--warn)"}})]})}function yv({projects:e,project:t,projectPath:n,onPick:s}){const[l,o]=N.useState(!1),a=N.useRef(null),[i,c]=N.useState(null),d=()=>{if(!l){const g=a.current?.getBoundingClientRect();c(g?{top:g.bottom+5,left:g.left}:null)}o(g=>!g)};N.useEffect(()=>{if(!l)return;const g=v=>{v.target.closest("[data-projsw]")||o(!1)};return window.addEventListener("mousedown",g),()=>window.removeEventListener("mousedown",g)},[l]);const u=e.filter(g=>g.initialized),f=t??"",h=n||(t??"pick a project");return r.jsxs("div",{"data-projsw":"1",style:{position:"relative",flexShrink:0},children:[r.jsxs("button",{ref:a,onClick:d,className:"row gap-6",title:"Switch project",style:{height:24,padding:"0 8px",borderRadius:6,cursor:"pointer",background:l?"var(--bg-hover)":"transparent",border:"1px solid "+(l?"var(--border-strong)":"transparent"),transition:"background var(--motion-fast), border-color var(--motion-fast)"},children:[r.jsx(z,{name:"folder",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"mono",style:{fontSize:11.5,color:"var(--text-primary)",maxWidth:280,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:h}),r.jsx(z,{name:"chevronDown",size:12,style:{color:"var(--text-muted)",flexShrink:0}})]}),l&&r.jsxs("div",{style:{position:"fixed",top:i?.top??34,left:i?.left??8,minWidth:264,background:"var(--bg-elevated)",border:"1px solid var(--border-strong)",borderRadius:9,boxShadow:"var(--shadow-pop)",padding:5,zIndex:60},children:[r.jsx("div",{className:"eyebrow",style:{padding:"5px 8px 6px"},children:"Indexed projects"}),r.jsxs("button",{className:"row gap-8",onClick:()=>{s(null),o(!1)},style:Qc(f===""),children:[r.jsx(z,{name:"folder",size:13,style:{color:"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"grow",style:{textAlign:"left",fontSize:12.5},children:"Primary project"}),f===""&&r.jsx(z,{name:"check",size:13,style:{color:"var(--accent)",flexShrink:0}})]}),u.map(g=>{const v=g.slug===f;return r.jsxs("button",{className:"row gap-8",onClick:()=>{s(g.slug),o(!1)},style:Qc(v),children:[r.jsx(z,{name:"folder",size:13,style:{color:v?"var(--accent)":"var(--text-muted)",flexShrink:0}}),r.jsx("span",{className:"grow mono",style:{textAlign:"left",fontSize:11.5,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:g.path}),(g.driftCount??0)>0&&r.jsxs("span",{className:"pill tabular",style:{fontSize:9.5,color:"var(--warn)",background:"var(--warn-soft)",flexShrink:0},children:[g.driftCount," drift"]}),v&&r.jsx(z,{name:"check",size:13,style:{color:"var(--accent)",flexShrink:0}})]},g.slug)}),!u.length&&r.jsx("div",{className:"muted",style:{padding:"6px 8px",fontSize:12},children:"No initialized projects found."})]})]})}function Qc(e){return{width:"100%",textAlign:"left",padding:"7px 8px",borderRadius:6,cursor:"pointer",border:"none",background:e?"var(--bg-active)":"transparent"}}function jv({status:e,projectless:t,projects:n,project:s,onPick:l,onRefresh:o,refreshing:a}){const i=(u,f,h)=>r.jsxs("div",{className:"row gap-6",style:{flexShrink:0},children:[r.jsx("span",{className:"muted",style:{fontSize:11},children:u}),r.jsx("span",{className:"mono tabular",style:{fontSize:11.5,color:h||"var(--text-secondary)"},children:f})]}),c=r.jsx("span",{style:{width:1,height:12,background:"var(--border-subtle)",flexShrink:0}}),d=e?.lastIndexed?new Date(e.lastIndexed).toLocaleString():"—";return r.jsxs("div",{style:{height:"var(--status-h)",flexShrink:0,display:"flex",alignItems:"center",gap:14,padding:"0 14px",borderBottom:"1px solid var(--border-subtle)",background:"var(--bg-panel-2)",overflow:"hidden",whiteSpace:"nowrap"},children:[r.jsx(yv,{projects:n,project:s,projectPath:e?.projectPath??null,onPick:l}),c,i("nodes",e?e.nodeCount.toLocaleString():t?"—":"…"),i("edges",e?e.edgeCount.toLocaleString():t?"—":"…"),c,i("drift",e?String(e.drift):"—",e?e.drift?"var(--warn)":"var(--success)":void 0),r.jsx("div",{className:"grow"}),i("indexed",d),r.jsx("button",{className:"btn btn-ghost btn-xs",onClick:o,title:"Refresh now","aria-label":"Refresh now",children:r.jsx(z,{name:"refresh",size:12,style:{animation:a?"spin 0.8s linear infinite":"none"}})})]})}const wv={fontFamily:"var(--font-mono)",fontSize:10,color:"var(--text-muted)",background:"var(--bg-canvas)",border:"1px solid var(--border-subtle)",borderRadius:4,padding:"2px 6px"};function Sv({onToggle:e,onOpenPalette:t}){return r.jsxs("div",{style:{height:44,flexShrink:0,display:"flex",alignItems:"center",gap:10,padding:"0 14px",borderBottom:"1px solid var(--border-subtle)",background:"var(--bg-canvas)"},children:[r.jsx("button",{className:"btn btn-ghost",onClick:e,style:{padding:6},title:"Toggle sidebar","aria-label":"Toggle sidebar",children:r.jsx(z,{name:"menu",size:16})}),r.jsxs("button",{onClick:t,className:"row gap-8",style:{flex:1,maxWidth:380,height:30,padding:"0 11px",background:"var(--bg-panel)",border:"1px solid var(--border-subtle)",borderRadius:8,cursor:"text",color:"var(--text-muted)",fontSize:12.5},children:[r.jsx(z,{name:"search",size:14}),r.jsx("span",{className:"grow",style:{textAlign:"left"},children:"Search or jump to…"}),r.jsx("kbd",{style:wv,children:"⌘K"})]}),r.jsx("div",{className:"grow"}),r.jsx(bv,{}),r.jsx("button",{className:"btn btn-ghost btn-sm",onClick:t,title:"Command palette","aria-label":"Command palette",children:r.jsx(z,{name:"command",size:14})})]})}function bv(){const[e,t]=N.useState(Sl()),n={dark:"light",light:"system",system:"dark"},s={dark:"moon",light:"sun",system:"monitor"},l=n[e];return r.jsx("button",{className:"btn btn-ghost btn-sm",title:"Theme: "+e+" — switch to "+l,"aria-label":"Theme: "+e+" — switch to "+l,onClick:()=>{bl(l),t(l)},children:r.jsx(z,{name:s[e],size:15})})}bl(Sl());Tm();Rp(_p());po.createRoot(document.getElementById("root")).render(r.jsx(Jp.StrictMode,{children:r.jsx(gv,{})}));
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
9
9
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
10
10
  <link rel="apple-touch-icon" sizes="180x180" href="/favicon-180.png" />
11
- <script type="module" crossorigin src="/assets/index-D8e4LiVb.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-CpBBlEO2.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-ezwX2EfG.css">
13
13
  </head>
14
14
  <body>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specship/specship",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specship/specship",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "description": "Supercharge Claude Code with semantic code intelligence. 94% fewer tool calls • 77% faster exploration • 100% local.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specship/specship-win32-arm64",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "description": "SpecShip self-contained bundle for win32-arm64",
5
5
  "os": [
6
6
  "win32"