@selvakumaresra/specship 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/commands/ss-domain.md +98 -0
  2. package/commands/ss-triage.md +177 -0
  3. package/dist/bin/specship.js +249 -0
  4. package/dist/bin/specship.js.map +1 -1
  5. package/dist/db/schema.sql +1 -1
  6. package/dist/db/spec-queries.d.ts +29 -0
  7. package/dist/db/spec-queries.d.ts.map +1 -1
  8. package/dist/db/spec-queries.js +63 -0
  9. package/dist/db/spec-queries.js.map +1 -1
  10. package/dist/enforce/enforce.d.ts +70 -0
  11. package/dist/enforce/enforce.d.ts.map +1 -0
  12. package/dist/enforce/enforce.js +125 -0
  13. package/dist/enforce/enforce.js.map +1 -0
  14. package/dist/extraction/specs/markdown-spec-extractor.d.ts +21 -0
  15. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  16. package/dist/extraction/specs/markdown-spec-extractor.js +144 -0
  17. package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  18. package/dist/fitness/fitness.d.ts +75 -0
  19. package/dist/fitness/fitness.d.ts.map +1 -0
  20. package/dist/fitness/fitness.js +204 -0
  21. package/dist/fitness/fitness.js.map +1 -0
  22. package/dist/graph/maintainability.d.ts +101 -0
  23. package/dist/graph/maintainability.d.ts.map +1 -0
  24. package/dist/graph/maintainability.js +278 -0
  25. package/dist/graph/maintainability.js.map +1 -0
  26. package/dist/index.d.ts +45 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +79 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/installer/instructions-template.d.ts +5 -4
  31. package/dist/installer/instructions-template.d.ts.map +1 -1
  32. package/dist/installer/instructions-template.js +10 -4
  33. package/dist/installer/instructions-template.js.map +1 -1
  34. package/dist/installer/targets/claude.d.ts.map +1 -1
  35. package/dist/installer/targets/claude.js +4 -0
  36. package/dist/installer/targets/claude.js.map +1 -1
  37. package/dist/installer/targets/shared.d.ts.map +1 -1
  38. package/dist/installer/targets/shared.js +4 -0
  39. package/dist/installer/targets/shared.js.map +1 -1
  40. package/dist/mcp/fitness-tool.d.ts +12 -0
  41. package/dist/mcp/fitness-tool.d.ts.map +1 -0
  42. package/dist/mcp/fitness-tool.js +46 -0
  43. package/dist/mcp/fitness-tool.js.map +1 -0
  44. package/dist/mcp/maintainability-tool.d.ts +13 -0
  45. package/dist/mcp/maintainability-tool.d.ts.map +1 -0
  46. package/dist/mcp/maintainability-tool.js +64 -0
  47. package/dist/mcp/maintainability-tool.js.map +1 -0
  48. package/dist/mcp/server-instructions.d.ts +1 -1
  49. package/dist/mcp/server-instructions.d.ts.map +1 -1
  50. package/dist/mcp/server-instructions.js +3 -2
  51. package/dist/mcp/server-instructions.js.map +1 -1
  52. package/dist/mcp/spec-tools.d.ts.map +1 -1
  53. package/dist/mcp/spec-tools.js +115 -1
  54. package/dist/mcp/spec-tools.js.map +1 -1
  55. package/dist/mcp/tools.d.ts +13 -0
  56. package/dist/mcp/tools.d.ts.map +1 -1
  57. package/dist/mcp/tools.js +75 -0
  58. package/dist/mcp/tools.js.map +1 -1
  59. package/dist/resolution/domain-gap-seed.d.ts +60 -0
  60. package/dist/resolution/domain-gap-seed.d.ts.map +1 -0
  61. package/dist/resolution/domain-gap-seed.js +87 -0
  62. package/dist/resolution/domain-gap-seed.js.map +1 -0
  63. package/dist/resolution/spec-link-resolver.d.ts +46 -1
  64. package/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  65. package/dist/resolution/spec-link-resolver.js +78 -0
  66. package/dist/resolution/spec-link-resolver.js.map +1 -1
  67. package/dist/server/routes/domain.js +0 -0
  68. package/dist/server/routes/maintainability.js +18 -0
  69. package/dist/server/server.js +4 -0
  70. package/dist/types.d.ts +3 -1
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js +6 -0
  73. package/dist/types.js.map +1 -1
  74. package/dist/web/chunk-EZZBWC7Z.js +1 -0
  75. package/dist/web/{chunk-UBOZGQNK.js → chunk-IZQXYQNQ.js} +1 -1
  76. package/dist/web/chunk-JQXCRIK2.js +1 -0
  77. package/dist/web/{chunk-ASZ77FMZ.js → chunk-JT2YIHPL.js} +1 -1
  78. package/dist/web/{chunk-WLIMNDS3.js → chunk-ONKHTXHJ.js} +1 -1
  79. package/dist/web/{chunk-FHZHD2ZG.js → chunk-P5JX67LT.js} +1 -1
  80. package/dist/web/{chunk-RJLLYZEQ.js → chunk-PDTQX2UL.js} +1 -1
  81. package/dist/web/{chunk-RASJHUXS.js → chunk-XWDR6MPC.js} +1 -1
  82. package/dist/web/{chunk-D5OCNEJA.js → chunk-ZG7H3XPL.js} +1 -1
  83. package/dist/web/index.html +1 -1
  84. package/dist/web/main-GYPY5V5H.js +1 -0
  85. package/package.json +1 -1
  86. package/dist/web/main-P33TUYUP.js +0 -1
@@ -1,2 +1,2 @@
1
- import{a as A,b as q,c as W}from"./chunk-T66XVKGB.js";import{a as Q}from"./chunk-DTRN7FZR.js";import{a as Y}from"./chunk-MC4DFIHG.js";import{a as K}from"./chunk-UYC52MBC.js";import{a as J}from"./chunk-2GBEK2GM.js";import{a as U}from"./chunk-SUZYBYDW.js";import{a as L,c as b}from"./chunk-GR72OOCN.js";import{c as G,d as B}from"./chunk-SHPTC4RL.js";import{a as V}from"./chunk-7RNS77UP.js";import{a as j}from"./chunk-E44X4RH2.js";import{Aa as l,Ga as P,I as w,Ia as v,Ka as c,M as f,N as C,Ta as E,Ua as y,Va as s,W as R,Wa as S,Xa as _,Ya as D,bb as N,ea as r,gb as O,ib as z,ka as F,lb as m,ra as u,sa as g,ua as I,va as M,vb as $,wa as T,xa as p,ya as a,za as o,zb as H}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var ee=()=>[0,1,2,3],te=()=>[0,1,2,3,4],Z=(i,e)=>e.id;function ne(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.fmt$(n.lastSessionCostStat().value)," ")}}function ie(i,e){i&1&&s(0," \xA0 ")}function ae(i,e){if(i&1&&l(0,"app-sparkline",11),i&2){let n=c();p("data",n.lastSessionCostStat().series)("width",64)("height",22)("fill",!0)}}function oe(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.lastSessionCostStat().delta)("invert",!0)}}function re(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.toolCallsStat().value.toLocaleString()," ")}}function se(i,e){i&1&&s(0," \xA0 ")}function le(i,e){if(i&1&&l(0,"app-sparkline",14),i&2){let n=c();p("data",n.toolCallsStat().series)("width",64)("height",22)("fill",!0)}}function de(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.toolCallsStat().delta)("invert",!0)}}function pe(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.subagentPctStat().value,"% ")}}function ce(i,e){i&1&&s(0," \xA0 ")}function me(i,e){if(i&1&&l(0,"app-sparkline",16),i&2){let n=c();p("data",n.subagentPctStat().series)("width",64)("height",22)("fill",!0)}}function ue(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.subagentPctStat().delta)("invert",!0)}}function ge(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.driftStat().value," ")}}function he(i,e){i&1&&s(0," \xA0 ")}function ve(i,e){i&1&&(a(0,"span",24),s(1,"seed"),o())}function _e(i,e){if(i&1&&(a(0,"span",31),s(1),o()),i&2){let n=c();r(),_(" ",n.urgentTipCount()," urgent ")}}function be(i,e){i&1&&l(0,"div",58)}function xe(i,e){i&1&&M(0,be,1,0,"div",58,I),i&2&&T(N(0,ee))}function fe(i,e){i&1&&(a(0,"div",34),s(1,"No tips yet. Run more sessions to populate."),o())}function Ce(i,e){if(i&1&&(a(0,"code",66),s(1),o()),i&2){let n=c().$implicit;r(),S(n.fix)}}function ye(i,e){if(i&1&&(a(0,"span",73),s(1),o()),i&2){let n=c().$implicit,t=c(2);E("color",t.tipSevColor(n.severity)),r(),S(n.saving)}}function Se(i,e){if(i&1){let n=P();a(0,"div",60)(1,"div",61),l(2,"app-icon",62),o(),a(3,"div",63)(4,"div",64),s(5),o(),a(6,"div",65),u(7,Ce,2,1,"code",66),l(8,"span",67),u(9,ye,2,3,"span",68),o()(),a(10,"div",69)(11,"button",70),v("click",function(){f(n);let d=c(2);return C(d.go("tips"))}),s(12,"Apply"),o(),a(13,"button",71),v("click",function(){let d=f(n).$implicit,h=c(2);return C(h.dismissTip(d.id))}),l(14,"app-icon",72),o()()()}if(i&2){let n=e.$implicit,t=c(2);E("border-left-color",t.tipSevColor(n.severity)),r(),E("color",t.tipSevColor(n.severity)),r(),p("name",t.tipIcon(n))("size",14),r(3),S(n.title),r(2),g(n.fix?7:-1),r(2),g(n.saving?9:-1),r(5),p("size",12)}}function ke(i,e){if(i&1&&M(0,Se,15,10,"div",59,Z),i&2){let n=c();T(n.visibleTips())}}function we(i,e){i&1&&l(0,"div",42)}function Me(i,e){i&1&&(a(0,"div",43),s(1," No tool calls in the selected window. "),o())}function Te(i,e){if(i&1){let n=P();a(0,"app-treemap",74),v("pick",function(){f(n);let d=c();return C(d.go("heatmap"))}),o()}if(i&2){let n=c();p("items",n.treemapItems())("height",116)("selKey",null)}}function Ee(i,e){i&1&&l(0,"div",75)}function Pe(i,e){i&1&&M(0,Ee,1,0,"div",75,I),i&2&&T(N(0,te))}function De(i,e){i&1&&(a(0,"div",34),s(1,"No prompts ingested for this range."),o())}function Oe(i,e){i&1&&l(0,"app-icon",80),i&2&&p("size",11)}function ze(i,e){if(i&1){let n=P();a(0,"div",77),v("click",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.enter",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.space",function(){f(n);let d=c(2);return C(d.go("sessions"))}),a(1,"div",78)(2,"div",79),u(3,Oe,1,1,"app-icon",80),s(4),o(),a(5,"div",81),l(6,"app-bar",82),o()(),a(7,"div",83)(8,"div",84),s(9),o(),a(10,"div",85),s(11),O(12,"number"),o()()()}if(i&2){let n=e.$implicit,t=c(2);r(3),g(n.is_sidechain?3:-1),r(),_(" ",n.text||"(no text)"," "),r(2),p("frac",t.promptFrac(n.cost_usd))("color",t.promptBarColor(n.cost_usd))("height",4),r(2),E("color",n.cost_usd/t.maxPromptCost()>.7?"var(--error)":"var(--text-primary)"),y("expensive",n.cost_usd/t.maxPromptCost()>.7),r(),_(" ",t.fmt$(n.cost_usd)," "),r(2),D(" ",t.fmtK(t.promptTotalTokens(n))," \xB7 ",z(12,12,t.promptCacheRate(n)*100,"1.0-0"),"% ")}}function Re(i,e){if(i&1&&M(0,ze,13,15,"div",76,Z),i&2){let n=c();T(n.topPrompts())}}function Ie(i,e){i&1&&l(0,"div",56)}function Ne(i,e){if(i&1&&(a(0,"div",86)(1,"div",87),s(2),O(3,"number"),o(),a(4,"div",88)(5,"div",40),s(6,"cache read rate"),o(),l(7,"app-delta",12),o()(),l(8,"div",89),a(9,"div",90)(10,"div",91)(11,"div",92),s(12,"Creation tokens"),o(),a(13,"div",93),s(14),o(),a(15,"div",94),s(16,"ephemeral"),o()(),a(17,"div",91)(18,"div",92),s(19,"Read tokens"),o(),a(20,"div",93),s(21),o(),a(22,"div",94),s(23,"charged at ~10%"),o()(),a(24,"div",91)(25,"div",92),s(26,"Saved this week"),o(),a(27,"div",95),s(28),o(),a(29,"div",94),s(30,"vs no cache"),o()(),a(31,"div",91)(32,"div",92),s(33,"WoW"),o(),a(34,"div",95),s(35),O(36,"number"),o(),a(37,"div",94),s(38,"more reuse"),o()()()),i&2){let n=c(),t=n.cache.state().data;r(2),_("",z(3,8,t.readRate*100,"1.0-0"),"%"),r(5),p("value",t.wowDelta)("invert",!1),r(7),S(n.fmtK(t.creationTokens)),r(7),S(n.fmtK(t.readTokens)),r(7),S(n.fmt$(t.dollarsSaved)),r(7),D(" ",t.wowDelta>=0?"+":"","",z(36,11,t.wowDelta*100,"1.0-0"),"% ")}}var X=class i{api=w(j);router=w(G);projects=w(V);conn=w(L);range=R("week");rangeOptions=[{value:"today",label:"Today"},{value:"week",label:"This week"},{value:"month",label:"This month"},{value:"all",label:"All time"}];status=b(this.api,()=>`/api/status${this.projects.projectQuery()}`);miniGraphSearch=b(this.api,()=>`/api/graph/search?q=on&limit=18${this.projects.projectQuery("&")}`);tips=b(this.api,()=>"/api/claude/tips");heatmap=b(this.api,()=>`/api/claude/heatmap?range=${this.range()}`);costs=b(this.api,()=>`/api/claude/costs?range=${this.range()}`);cache=b(this.api,()=>`/api/claude/cache?range=${this.range()}`);sessions=b(this.api,()=>`/api/claude/sessions?range=${this.range()}&limit=10`);stats=b(this.api,()=>`/api/claude/stats?range=${this.range()}`);EMPTY_METRIC={value:0,delta:0,series:[]};lastSessionCostStat=m(()=>this.stats.state().data?.lastSessionCost??this.EMPTY_METRIC);toolCallsStat=m(()=>this.stats.state().data?.toolCalls??this.EMPTY_METRIC);subagentPctStat=m(()=>this.stats.state().data?.subagentPct??this.EMPTY_METRIC);driftStat=m(()=>this.stats.state().data?.drift??this.EMPTY_METRIC);lastSession=m(()=>(this.sessions.state().data?.sessions??[])[0]??null);lastSessionCost=m(()=>this.lastSession()?.total_cost_usd??0);toolCallCount=m(()=>(this.heatmap.state().data?.tools??[]).reduce((n,t)=>n+(t.calls??0),0));subagentShare=m(()=>{let e=this.heatmap.state().data?.subagents??[],n=e.find(x=>x.type==="subagent"),t=e.find(x=>x.type==="main"),d=n?.cost??0,h=t?.cost??0,k=d+h;return k>0?Math.round(d/k*100):0});driftCount=m(()=>this.status.state().data?.drift??0);nodeCountLabel=m(()=>this.status.state().data?.nodeCount??0);urgentTipCount=m(()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity==="error").length);dismissedTips=R(new Set);dismissTip(e){this.dismissedTips.update(n=>{let t=new Set(n);return t.add(e),t})}isTipDismissed(e){return this.dismissedTips().has(e)}visibleTips=m(()=>{let e=this.dismissedTips();return(this.tips.state().data?.tips??[]).filter(n=>!e.has(n.id)).slice(0,4)});treemapItems=m(()=>{let e=(this.heatmap.state().data?.files??[]).slice(0,30);if(!e.length)return[];let n=Math.max(1,...e.map(t=>t.resultBytes&&t.calls?t.resultBytes/t.calls:0));return e.map(t=>{let d=t.calls>0?t.resultBytes/t.calls:0,h=Math.min(1,d/n);return{key:t.path,label:A(t.path),value:t.calls,intensity:h,sub:t.calls+" calls",title:`${t.path}
1
+ import{a as A,b as q,c as W}from"./chunk-T66XVKGB.js";import{a as Q}from"./chunk-DTRN7FZR.js";import{a as Y}from"./chunk-MC4DFIHG.js";import{a as K}from"./chunk-UYC52MBC.js";import{a as J}from"./chunk-2GBEK2GM.js";import{a as U}from"./chunk-SUZYBYDW.js";import{c as G,d as B}from"./chunk-SHPTC4RL.js";import{a as L,c as b}from"./chunk-GR72OOCN.js";import{a as V}from"./chunk-7RNS77UP.js";import{a as j}from"./chunk-E44X4RH2.js";import{Aa as l,Ga as P,I as w,Ia as v,Ka as c,M as f,N as C,Ta as E,Ua as y,Va as s,W as R,Wa as S,Xa as _,Ya as D,bb as N,ea as r,gb as O,ib as z,ka as F,lb as m,ra as u,sa as g,ua as I,va as M,vb as $,wa as T,xa as p,ya as a,za as o,zb as H}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var ee=()=>[0,1,2,3],te=()=>[0,1,2,3,4],Z=(i,e)=>e.id;function ne(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.fmt$(n.lastSessionCostStat().value)," ")}}function ie(i,e){i&1&&s(0," \xA0 ")}function ae(i,e){if(i&1&&l(0,"app-sparkline",11),i&2){let n=c();p("data",n.lastSessionCostStat().series)("width",64)("height",22)("fill",!0)}}function oe(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.lastSessionCostStat().delta)("invert",!0)}}function re(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.toolCallsStat().value.toLocaleString()," ")}}function se(i,e){i&1&&s(0," \xA0 ")}function le(i,e){if(i&1&&l(0,"app-sparkline",14),i&2){let n=c();p("data",n.toolCallsStat().series)("width",64)("height",22)("fill",!0)}}function de(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.toolCallsStat().delta)("invert",!0)}}function pe(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.subagentPctStat().value,"% ")}}function ce(i,e){i&1&&s(0," \xA0 ")}function me(i,e){if(i&1&&l(0,"app-sparkline",16),i&2){let n=c();p("data",n.subagentPctStat().series)("width",64)("height",22)("fill",!0)}}function ue(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.subagentPctStat().delta)("invert",!0)}}function ge(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.driftStat().value," ")}}function he(i,e){i&1&&s(0," \xA0 ")}function ve(i,e){i&1&&(a(0,"span",24),s(1,"seed"),o())}function _e(i,e){if(i&1&&(a(0,"span",31),s(1),o()),i&2){let n=c();r(),_(" ",n.urgentTipCount()," urgent ")}}function be(i,e){i&1&&l(0,"div",58)}function xe(i,e){i&1&&M(0,be,1,0,"div",58,I),i&2&&T(N(0,ee))}function fe(i,e){i&1&&(a(0,"div",34),s(1,"No tips yet. Run more sessions to populate."),o())}function Ce(i,e){if(i&1&&(a(0,"code",66),s(1),o()),i&2){let n=c().$implicit;r(),S(n.fix)}}function ye(i,e){if(i&1&&(a(0,"span",73),s(1),o()),i&2){let n=c().$implicit,t=c(2);E("color",t.tipSevColor(n.severity)),r(),S(n.saving)}}function Se(i,e){if(i&1){let n=P();a(0,"div",60)(1,"div",61),l(2,"app-icon",62),o(),a(3,"div",63)(4,"div",64),s(5),o(),a(6,"div",65),u(7,Ce,2,1,"code",66),l(8,"span",67),u(9,ye,2,3,"span",68),o()(),a(10,"div",69)(11,"button",70),v("click",function(){f(n);let d=c(2);return C(d.go("tips"))}),s(12,"Apply"),o(),a(13,"button",71),v("click",function(){let d=f(n).$implicit,h=c(2);return C(h.dismissTip(d.id))}),l(14,"app-icon",72),o()()()}if(i&2){let n=e.$implicit,t=c(2);E("border-left-color",t.tipSevColor(n.severity)),r(),E("color",t.tipSevColor(n.severity)),r(),p("name",t.tipIcon(n))("size",14),r(3),S(n.title),r(2),g(n.fix?7:-1),r(2),g(n.saving?9:-1),r(5),p("size",12)}}function ke(i,e){if(i&1&&M(0,Se,15,10,"div",59,Z),i&2){let n=c();T(n.visibleTips())}}function we(i,e){i&1&&l(0,"div",42)}function Me(i,e){i&1&&(a(0,"div",43),s(1," No tool calls in the selected window. "),o())}function Te(i,e){if(i&1){let n=P();a(0,"app-treemap",74),v("pick",function(){f(n);let d=c();return C(d.go("heatmap"))}),o()}if(i&2){let n=c();p("items",n.treemapItems())("height",116)("selKey",null)}}function Ee(i,e){i&1&&l(0,"div",75)}function Pe(i,e){i&1&&M(0,Ee,1,0,"div",75,I),i&2&&T(N(0,te))}function De(i,e){i&1&&(a(0,"div",34),s(1,"No prompts ingested for this range."),o())}function Oe(i,e){i&1&&l(0,"app-icon",80),i&2&&p("size",11)}function ze(i,e){if(i&1){let n=P();a(0,"div",77),v("click",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.enter",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.space",function(){f(n);let d=c(2);return C(d.go("sessions"))}),a(1,"div",78)(2,"div",79),u(3,Oe,1,1,"app-icon",80),s(4),o(),a(5,"div",81),l(6,"app-bar",82),o()(),a(7,"div",83)(8,"div",84),s(9),o(),a(10,"div",85),s(11),O(12,"number"),o()()()}if(i&2){let n=e.$implicit,t=c(2);r(3),g(n.is_sidechain?3:-1),r(),_(" ",n.text||"(no text)"," "),r(2),p("frac",t.promptFrac(n.cost_usd))("color",t.promptBarColor(n.cost_usd))("height",4),r(2),E("color",n.cost_usd/t.maxPromptCost()>.7?"var(--error)":"var(--text-primary)"),y("expensive",n.cost_usd/t.maxPromptCost()>.7),r(),_(" ",t.fmt$(n.cost_usd)," "),r(2),D(" ",t.fmtK(t.promptTotalTokens(n))," \xB7 ",z(12,12,t.promptCacheRate(n)*100,"1.0-0"),"% ")}}function Re(i,e){if(i&1&&M(0,ze,13,15,"div",76,Z),i&2){let n=c();T(n.topPrompts())}}function Ie(i,e){i&1&&l(0,"div",56)}function Ne(i,e){if(i&1&&(a(0,"div",86)(1,"div",87),s(2),O(3,"number"),o(),a(4,"div",88)(5,"div",40),s(6,"cache read rate"),o(),l(7,"app-delta",12),o()(),l(8,"div",89),a(9,"div",90)(10,"div",91)(11,"div",92),s(12,"Creation tokens"),o(),a(13,"div",93),s(14),o(),a(15,"div",94),s(16,"ephemeral"),o()(),a(17,"div",91)(18,"div",92),s(19,"Read tokens"),o(),a(20,"div",93),s(21),o(),a(22,"div",94),s(23,"charged at ~10%"),o()(),a(24,"div",91)(25,"div",92),s(26,"Saved this week"),o(),a(27,"div",95),s(28),o(),a(29,"div",94),s(30,"vs no cache"),o()(),a(31,"div",91)(32,"div",92),s(33,"WoW"),o(),a(34,"div",95),s(35),O(36,"number"),o(),a(37,"div",94),s(38,"more reuse"),o()()()),i&2){let n=c(),t=n.cache.state().data;r(2),_("",z(3,8,t.readRate*100,"1.0-0"),"%"),r(5),p("value",t.wowDelta)("invert",!1),r(7),S(n.fmtK(t.creationTokens)),r(7),S(n.fmtK(t.readTokens)),r(7),S(n.fmt$(t.dollarsSaved)),r(7),D(" ",t.wowDelta>=0?"+":"","",z(36,11,t.wowDelta*100,"1.0-0"),"% ")}}var X=class i{api=w(j);router=w(G);projects=w(V);conn=w(L);range=R("week");rangeOptions=[{value:"today",label:"Today"},{value:"week",label:"This week"},{value:"month",label:"This month"},{value:"all",label:"All time"}];status=b(this.api,()=>`/api/status${this.projects.projectQuery()}`);miniGraphSearch=b(this.api,()=>`/api/graph/search?q=on&limit=18${this.projects.projectQuery("&")}`);tips=b(this.api,()=>"/api/claude/tips");heatmap=b(this.api,()=>`/api/claude/heatmap?range=${this.range()}`);costs=b(this.api,()=>`/api/claude/costs?range=${this.range()}`);cache=b(this.api,()=>`/api/claude/cache?range=${this.range()}`);sessions=b(this.api,()=>`/api/claude/sessions?range=${this.range()}&limit=10`);stats=b(this.api,()=>`/api/claude/stats?range=${this.range()}`);EMPTY_METRIC={value:0,delta:0,series:[]};lastSessionCostStat=m(()=>this.stats.state().data?.lastSessionCost??this.EMPTY_METRIC);toolCallsStat=m(()=>this.stats.state().data?.toolCalls??this.EMPTY_METRIC);subagentPctStat=m(()=>this.stats.state().data?.subagentPct??this.EMPTY_METRIC);driftStat=m(()=>this.stats.state().data?.drift??this.EMPTY_METRIC);lastSession=m(()=>(this.sessions.state().data?.sessions??[])[0]??null);lastSessionCost=m(()=>this.lastSession()?.total_cost_usd??0);toolCallCount=m(()=>(this.heatmap.state().data?.tools??[]).reduce((n,t)=>n+(t.calls??0),0));subagentShare=m(()=>{let e=this.heatmap.state().data?.subagents??[],n=e.find(x=>x.type==="subagent"),t=e.find(x=>x.type==="main"),d=n?.cost??0,h=t?.cost??0,k=d+h;return k>0?Math.round(d/k*100):0});driftCount=m(()=>this.status.state().data?.drift??0);nodeCountLabel=m(()=>this.status.state().data?.nodeCount??0);urgentTipCount=m(()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity==="error").length);dismissedTips=R(new Set);dismissTip(e){this.dismissedTips.update(n=>{let t=new Set(n);return t.add(e),t})}isTipDismissed(e){return this.dismissedTips().has(e)}visibleTips=m(()=>{let e=this.dismissedTips();return(this.tips.state().data?.tips??[]).filter(n=>!e.has(n.id)).slice(0,4)});treemapItems=m(()=>{let e=(this.heatmap.state().data?.files??[]).slice(0,30);if(!e.length)return[];let n=Math.max(1,...e.map(t=>t.resultBytes&&t.calls?t.resultBytes/t.calls:0));return e.map(t=>{let d=t.calls>0?t.resultBytes/t.calls:0,h=Math.min(1,d/n);return{key:t.path,label:A(t.path),value:t.calls,intensity:h,sub:t.calls+" calls",title:`${t.path}
2
2
  ${t.calls} calls \xB7 ${this.fmtK(Math.round(d))}/call`}})});topPrompts=m(()=>(this.costs.state().data?.topPrompts??[]).slice(0,8));maxPromptCost=m(()=>Math.max(.01,...this.topPrompts().map(e=>e.cost_usd??0)));rangeTotal=m(()=>(this.costs.state().data?.series??[]).reduce((n,t)=>n+(t.cost??0),0));liveSource=m(()=>this.conn.online()?"live":"offline");miniGraphSource=m(()=>(this.miniGraphSearch.state().data?.results?.length??0)>0?"api":"seed");miniGraphNodes=m(()=>{let e=this.miniGraphSearch.state().data?.results??[];return e.length>0?Ge(e.slice(0,18).map(n=>({id:n.node.id,label:n.node.name,sub:n.node.filePath?.split("/").slice(-2).join("/"),kind:n.node.kind}))):Fe});miniGraphEdges=m(()=>{if(this.miniGraphSource()==="api"){let e=this.miniGraphNodes(),n=[];for(let t=1;t<e.length;t++){let d=e[Math.floor(Math.random()*t)],h=e[t];d&&h&&n.push({from:d.id,to:h.id,kind:"calls"})}return n}return $e});onMiniGraphPick(e){this.router.navigate(["/graph"],{queryParams:{focus:e}})}setRange(e){this.range.set(e)}go(e){this.router.navigate(["/"+e])}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptCacheRate(e){let n=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return n>0?(e.cache_read_tokens??0)/n:0}promptTotalTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}promptBarColor(e){return e/this.maxPromptCost()>.7?"var(--error)":"var(--accent)"}promptFrac(e){return Math.max(0,Math.min(1,e/this.maxPromptCost()))}tipSevColor(e){return e==="error"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)"}tipIcon(e){return e.icon?e.icon:e.severity==="error"?"cancel":e.severity==="warn"?"warn":"info"}static \u0275fac=function(n){return new(n||i)};static \u0275cmp=F({type:i,selectors:[["app-dashboard"]],decls:122,vars:48,consts:[[1,"scroll-y","dashboard"],["icon","dashboard","title","Dashboard",3,"sub"],["actions",""],["size","sm",3,"change","options","value"],[1,"stat-grid"],["type","button",1,"stat-tile",3,"click"],[1,"row","gap-8","stat-eyebrow"],["name","coins",2,"color","var(--accent)",3,"size"],[1,"eyebrow",2,"letter-spacing","0.04em"],[1,"row","stat-value-row"],[1,"stat-value","tabular"],["color","var(--accent)",3,"data","width","height","fill"],[3,"value","invert"],["name","wrench",2,"color","var(--node-spec)",3,"size"],["color","var(--node-spec)",3,"data","width","height","fill"],["name","bot",2,"color","var(--node-code)",3,"size"],["color","var(--node-code)",3,"data","width","height","fill"],["name","drift",2,"color","var(--warn)",3,"size"],[1,"center-grid"],[1,"card","graph-card"],[1,"card-head"],[1,"card-title","row","gap-8"],["name","graph",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px","font-weight","400"],["title","No graph data yet \u2014 illustrative",1,"pill","seed-pill"],["routerLink","/graph",1,"btn","btn-ghost","btn-xs"],["name","arrowRight",3,"size"],[1,"mini-graph"],[3,"nodeClick","nodes","edges"],[1,"card","tips-card"],["name","tips",2,"color","var(--warn)",3,"size"],[1,"pill",2,"font-size","10px","background","var(--error-soft)","color","var(--error)"],["routerLink","/tips",1,"btn","btn-ghost","btn-xs"],[1,"scroll-y","tips-body"],[1,"tip-empty"],[1,"card","card-pad","heatmap-card"],[1,"row","heatmap-head"],[1,"row","gap-8"],["name","flame",2,"color","var(--warn)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[1,"muted",2,"font-size","11px"],["routerLink","/heatmap",1,"btn","btn-ghost","btn-xs"],[1,"skel",2,"height","116px","border-radius","7px"],[1,"tip-empty",2,"height","116px","display","grid","place-items","center"],[3,"items","height","selKey"],[1,"row","gap-10","heatmap-legend"],[1,"muted",2,"font-size","10px"],[1,"heatmap-gradient"],[1,"muted",2,"font-size","9.5px"],[1,"bottom-grid"],[1,"card","card-pad","prompts-card"],[1,"row","prompts-head"],["routerLink","/costs",1,"btn","btn-ghost","btn-xs"],[1,"col"],[1,"card","card-pad","cache-card"],["name","database",2,"color","var(--node-route)",3,"size"],[1,"skel",2,"height","70px","border-radius","5px"],[1,"dash-footer","mono","muted"],[1,"skel",2,"height","64px","border-radius","8px"],[1,"tip-row",3,"border-left-color"],[1,"tip-row"],[1,"tip-sev-icon"],[3,"name","size"],[1,"grow","tip-body-col",2,"min-width","0"],[1,"tip-title"],[1,"row","gap-8","tip-meta-row"],[1,"mono","tip-fix"],[1,"grow"],[1,"pill",2,"font-size","10px","color","inherit","background","transparent",3,"color"],[1,"row","gap-4",2,"flex-shrink","0"],["type","button",1,"btn","btn-secondary","btn-xs",3,"click"],["type","button","title","Dismiss",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"pill",2,"font-size","10px","color","inherit","background","transparent"],[3,"pick","items","height","selKey"],[1,"skel",2,"height","26px","margin","4px 0","border-radius","4px"],["role","button","tabindex","0",1,"prompt-row"],["role","button","tabindex","0",1,"prompt-row",3,"click","keydown.enter","keydown.space"],[1,"grow","prompt-left",2,"min-width","0"],[1,"prompt-text"],["name","bot",2,"color","var(--node-code)","margin-right","5px","vertical-align","-1px",3,"size"],[2,"margin-top","4px","width","70%"],[3,"frac","color","height"],[1,"prompt-right"],[1,"mono","tabular","prompt-cost"],[1,"mono","muted",2,"font-size","10px"],[1,"row","cache-headline"],[1,"tabular","cache-rate"],[2,"padding-bottom","3px"],[1,"cache-divider"],[1,"cache-kv-grid"],[1,"kv"],[1,"kv-label"],[1,"kv-value","mono","tabular"],[1,"kv-sub","mono","muted"],[1,"kv-value","mono","tabular",2,"color","var(--success)"]],template:function(n,t){n&1&&(a(0,"div",0)(1,"app-page-head",1)(2,"div",2)(3,"app-segmented",3),v("change",function(h){return t.setRange(h)}),o()()(),a(4,"div",4)(5,"button",5),v("click",function(){return t.go("sessions")}),a(6,"div",6),l(7,"app-icon",7),a(8,"span",8),s(9,"Last session cost"),o()(),a(10,"div",9)(11,"div",10),u(12,ne,1,1)(13,ie,1,0),o(),u(14,ae,1,4,"app-sparkline",11),o(),u(15,oe,1,2,"app-delta",12),o(),a(16,"button",5),v("click",function(){return t.go("heatmap")}),a(17,"div",6),l(18,"app-icon",13),a(19,"span",8),s(20),o()(),a(21,"div",9)(22,"div",10),u(23,re,1,1)(24,se,1,0),o(),u(25,le,1,4,"app-sparkline",14),o(),u(26,de,1,2,"app-delta",12),o(),a(27,"button",5),v("click",function(){return t.go("heatmap")}),a(28,"div",6),l(29,"app-icon",15),a(30,"span",8),s(31,"Subagent spend"),o()(),a(32,"div",9)(33,"div",10),u(34,pe,1,1)(35,ce,1,0),o(),u(36,me,1,4,"app-sparkline",16),o(),u(37,ue,1,2,"app-delta",12),o(),a(38,"button",5),v("click",function(){return t.go("drift")}),a(39,"div",6),l(40,"app-icon",17),a(41,"span",8),s(42,"Drift queue"),o()(),a(43,"div",9)(44,"div",10),u(45,ge,1,1)(46,he,1,0),o()()()(),a(47,"div",18)(48,"div",19)(49,"div",20)(50,"div",21),l(51,"app-icon",22),a(52,"span"),s(53,"Recent neighborhood"),o(),a(54,"span",23),s(55,"\xB7 last edited files"),o(),u(56,ve,2,0,"span",24),o(),a(57,"a",25),s(58," Open graph "),l(59,"app-icon",26),o()(),a(60,"div",27)(61,"app-graph-canvas",28),v("nodeClick",function(h){return t.onMiniGraphPick(h)}),o()()(),a(62,"div",29)(63,"div",20)(64,"div",21),l(65,"app-icon",30),a(66,"span"),s(67,"Tips"),o(),u(68,_e,2,1,"span",31),o(),a(69,"a",32),s(70,"All"),o()(),a(71,"div",33),u(72,xe,2,1)(73,fe,2,0,"div",34)(74,ke,2,0),o()()(),a(75,"div",35)(76,"div",36)(77,"div",37),l(78,"app-icon",38),a(79,"span",39),s(80,"Tool-call heatmap"),o(),a(81,"span",40),s(82,"\xB7 area = calls, color = tokens / call"),o()(),a(83,"a",41),s(84," Open heatmap "),l(85,"app-icon",26),o()(),u(86,we,1,0,"div",42)(87,Me,2,0,"div",43)(88,Te,1,3,"app-treemap",44),a(89,"div",45)(90,"span",46),s(91,"tokens / call"),o(),l(92,"div",47),a(93,"span",48),s(94,"efficient \u2192 wasteful"),o()()(),a(95,"div",49)(96,"div",50)(97,"div",51)(98,"div",37),l(99,"app-icon",7),a(100,"span",39),s(101,"Recent prompts"),o(),a(102,"span",40),s(103,"\xB7 by cost"),o()(),a(104,"a",52),s(105,"Cost ranking"),o()(),a(106,"div",53),u(107,Pe,2,1)(108,De,2,0,"div",34)(109,Re,2,0),o()(),a(110,"div",54)(111,"div",37),l(112,"app-icon",55),a(113,"span",39),s(114,"Cache analytics"),o()(),u(115,Ie,1,0,"div",56)(116,Ne,39,14),o()(),a(117,"footer",57),s(118),a(119,"span"),s(120,"\u25CF"),o(),s(121),o()()),n&2&&(r(),p("sub","specship \xB7 "+t.nodeCountLabel().toLocaleString()+" nodes \xB7 last session "+t.fmt$(t.lastSessionCost())),r(2),p("options",t.rangeOptions)("value",t.range()),r(4),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?13:12),r(2),g(t.lastSessionCostStat().series.length>0?14:-1),r(),g(t.lastSessionCostStat().delta!==0?15:-1),r(3),p("size",13),r(2),_("Tool calls \xB7 ",t.range()),r(2),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?24:23),r(2),g(t.toolCallsStat().series.length>0?25:-1),r(),g(t.toolCallsStat().delta!==0?26:-1),r(3),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?35:34),r(2),g(t.subagentPctStat().series.length>0?36:-1),r(),g(t.subagentPctStat().delta!==0?37:-1),r(3),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?46:45),r(6),p("size",14),r(5),g(t.miniGraphSource()==="seed"?56:-1),r(3),p("size",11),r(2),p("nodes",t.miniGraphNodes())("edges",t.miniGraphEdges()),r(4),p("size",14),r(3),g(t.urgentTipCount()>0?68:-1),r(4),g(t.tips.state().loading?72:t.visibleTips().length===0?73:74),r(6),p("size",14),r(7),p("size",11),r(),g(t.heatmap.state().loading?86:t.treemapItems().length===0?87:88),r(13),p("size",14),r(8),g(t.costs.state().loading?107:t.topPrompts().length===0?108:109),r(5),p("size",14),r(3),g(t.cache.state().loading?115:t.cache.state().data?116:-1),r(3),D(" ",t.range()," window total: ",t.fmt$(t.rangeTotal())," \xB7 "),r(),y("dot-live",t.liveSource()==="live")("dot-mock",t.liveSource()==="offline"),r(2),_(" ",t.liveSource()==="live"?"Live":"Offline"," "))},dependencies:[B,H,K,U,Y,Q,q,W,J,$],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.dashboard[_ngcontent-%COMP%]{flex:1;padding:18px;color:var(--text-primary);background:var(--bg-canvas)}.stat-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}.stat-tile[_ngcontent-%COMP%]{text-align:left;padding:11px 13px;cursor:pointer;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);display:flex;flex-direction:column;gap:6px;color:var(--text-primary);font-family:inherit;transition:background .1s,border-color .1s}.stat-tile[_ngcontent-%COMP%]:hover{background:var(--bg-panel-2);border-color:var(--border-strong)}.stat-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.stat-value-row[_ngcontent-%COMP%]{justify-content:space-between;align-items:flex-end;gap:8px}.stat-value[_ngcontent-%COMP%]{font-size:23px;font-weight:650;letter-spacing:-.02em;line-height:1;min-height:23px}.center-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-bottom:14px}.graph-card[_ngcontent-%COMP%], .tips-card[_ngcontent-%COMP%]{height:340px;display:flex;flex-direction:column;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);overflow:hidden}.card-head[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:11px 13px;border-bottom:1px solid var(--border-subtle);flex-shrink:0}.card-title[_ngcontent-%COMP%]{font-weight:600;font-size:12.5px;display:inline-flex;align-items:center;gap:8px}.mini-graph[_ngcontent-%COMP%]{flex:1;min-height:0;overflow:hidden;border-bottom-left-radius:var(--r-lg);border-bottom-right-radius:var(--r-lg)}.mini-graph[_ngcontent-%COMP%] app-graph-canvas[_ngcontent-%COMP%]{display:block;width:100%;height:100%}.seed-pill[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft);font-size:9.5px;font-weight:600;padding:1px 6px}.tips-body[_ngcontent-%COMP%]{flex:1;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:0}.tip-empty[_ngcontent-%COMP%]{color:var(--text-muted);font-size:12px;text-align:center;padding:12px}.tip-row[_ngcontent-%COMP%]{display:flex;gap:10px;padding:10px 12px;border-radius:8px;background:var(--bg-panel-2);border:1px solid var(--border-subtle);border-left-width:2.5px;animation:_ngcontent-%COMP%_slideInRight .2s ease;flex-shrink:0}.tip-sev-icon[_ngcontent-%COMP%]{flex-shrink:0;margin-top:1px}.tip-body-col[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:0}.tip-title[_ngcontent-%COMP%]{font-size:12.5px;font-weight:550;line-height:1.35;text-wrap:pretty}.tip-meta-row[_ngcontent-%COMP%]{margin-top:7px}.tip-fix[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-secondary);background:var(--bg-canvas);padding:2px 6px;border-radius:4px;border:1px solid var(--border-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}.heatmap-card[_ngcontent-%COMP%]{margin-bottom:14px}.heatmap-head[_ngcontent-%COMP%]{justify-content:space-between;margin-bottom:10px}.heatmap-legend[_ngcontent-%COMP%]{margin-top:9px;align-items:center}.heatmap-gradient[_ngcontent-%COMP%]{width:96px;height:6px;border-radius:999px;background:linear-gradient(90deg,var(--node-route),var(--warn),var(--error))}.bottom-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.4fr 1fr;gap:12px}.prompts-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:0}.prompts-head[_ngcontent-%COMP%]{justify-content:space-between;margin-bottom:6px}.prompt-row[_ngcontent-%COMP%]{display:flex;gap:10px;padding:7px 4px;border-radius:6px;cursor:pointer;align-items:center}.prompt-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.prompt-text[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prompt-right[_ngcontent-%COMP%]{text-align:right;flex-shrink:0}.prompt-cost[_ngcontent-%COMP%]{font-size:12px;font-weight:600}.prompt-cost.expensive[_ngcontent-%COMP%]{color:var(--error)}.cache-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.cache-headline[_ngcontent-%COMP%]{align-items:flex-end;gap:10px}.cache-rate[_ngcontent-%COMP%]{font-size:38px;font-weight:700;letter-spacing:-.03em;line-height:.9;color:var(--node-route)}.cache-divider[_ngcontent-%COMP%]{height:1px;background:var(--border-subtle)}.cache-kv-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:10px 14px}.kv[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px}.kv-label[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px}.kv-value[_ngcontent-%COMP%]{font-size:15px;font-weight:600}.kv-sub[_ngcontent-%COMP%]{font-size:9.5px}.dash-footer[_ngcontent-%COMP%]{margin-top:16px;text-align:right;font-size:10px}.dot-live[_ngcontent-%COMP%]{color:var(--success)}.dot-mock[_ngcontent-%COMP%]{color:var(--warn)}@keyframes _ngcontent-%COMP%_slideInRight{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}'],changeDetection:0})},Fe=[{id:"s-1",label:"validateSession",sub:"src/auth.ts",kind:"function",x:0,y:0},{id:"s-2",label:"checkExpiry",sub:"src/auth.ts",kind:"method",x:-180,y:-70},{id:"s-3",label:"signToken",sub:"src/auth.ts",kind:"function",x:-180,y:50},{id:"s-4",label:"AuthRoute",sub:"src/routes/auth.ts",kind:"route",x:200,y:-90},{id:"s-5",label:"login",sub:"src/routes/auth.ts",kind:"function",x:200,y:30},{id:"s-6",label:"logout",sub:"src/routes/auth.ts",kind:"function",x:230,y:110},{id:"s-7",label:"auth.test.ts",sub:"test/auth.test.ts",kind:"test",x:-240,y:140},{id:"s-8",label:"session.test.ts",sub:"test/session.test.ts",kind:"test",x:-100,y:180},{id:"s-9",label:"REQ-AUTH-005",sub:"reject expired tokens",kind:"spec",state:"drifted",x:30,y:-180},{id:"s-10",label:"REQ-AUTH-001",sub:"sign session tokens",kind:"spec",state:"verified",x:-150,y:-190},{id:"s-11",label:"User",sub:"src/types/user.ts",kind:"class",x:-340,y:-10},{id:"s-12",label:"Session",sub:"src/types/session.ts",kind:"class",x:60,y:130},{id:"s-13",label:"jwtSign",sub:"src/lib/jwt.ts",kind:"function",x:-340,y:80},{id:"s-14",label:"jwtVerify",sub:"src/lib/jwt.ts",kind:"function",x:350,y:-10},{id:"s-15",label:"tokenStore",sub:"src/db/tokens.ts",kind:"function",x:350,y:90}],$e=[{from:"s-1",to:"s-2",kind:"calls"},{from:"s-1",to:"s-3",kind:"calls"},{from:"s-4",to:"s-5",kind:"calls"},{from:"s-4",to:"s-6",kind:"calls"},{from:"s-5",to:"s-1",kind:"calls"},{from:"s-6",to:"s-1",kind:"calls"},{from:"s-3",to:"s-13",kind:"calls"},{from:"s-2",to:"s-14",kind:"calls"},{from:"s-1",to:"s-12",kind:"references"},{from:"s-5",to:"s-11",kind:"references"},{from:"s-9",to:"s-1",kind:"implements"},{from:"s-10",to:"s-3",kind:"implements"},{from:"s-7",to:"s-1",kind:"references"},{from:"s-8",to:"s-12",kind:"references"},{from:"s-14",to:"s-15",kind:"calls"}];function Ge(i){if(i.length===0)return[];let e=i[0],n=i.slice(1),t=[{id:e.id,label:e.label,sub:e.sub,kind:e.kind,x:0,y:0}],d=220;for(let h=0;h<n.length;h++){let k=h/n.length*Math.PI*2-Math.PI/2,x=n[h];t.push({id:x.id,label:x.label,sub:x.sub,kind:x.kind,x:Math.cos(k)*d,y:Math.sin(k)*d})}return t}export{X as Dashboard};
@@ -142,5 +142,5 @@
142
142
  })();
143
143
  </script>
144
144
  <app-root></app-root>
145
- <link rel="modulepreload" href="chunk-Y6WWDS4R.js"><link rel="modulepreload" href="chunk-GR72OOCN.js"><link rel="modulepreload" href="chunk-SHPTC4RL.js"><link rel="modulepreload" href="chunk-7RNS77UP.js"><link rel="modulepreload" href="chunk-E44X4RH2.js"><link rel="modulepreload" href="chunk-PDN6QYGJ.js"><link rel="modulepreload" href="chunk-Q7L6LLAK.js"><script src="main-P33TUYUP.js" type="module"></script></body>
145
+ <link rel="modulepreload" href="chunk-Y6WWDS4R.js"><link rel="modulepreload" href="chunk-SHPTC4RL.js"><link rel="modulepreload" href="chunk-GR72OOCN.js"><link rel="modulepreload" href="chunk-7RNS77UP.js"><link rel="modulepreload" href="chunk-E44X4RH2.js"><link rel="modulepreload" href="chunk-PDN6QYGJ.js"><link rel="modulepreload" href="chunk-Q7L6LLAK.js"><script src="main-GYPY5V5H.js" type="module"></script></body>
146
146
  </html>
@@ -0,0 +1 @@
1
+ import{a as G,b as he}from"./chunk-Y6WWDS4R.js";import{b as ce,c as z,d as me,e as ue,f as ge}from"./chunk-SHPTC4RL.js";import{a as fe,b as ve,c as L}from"./chunk-GR72OOCN.js";import{a as I}from"./chunk-7RNS77UP.js";import{a as H}from"./chunk-E44X4RH2.js";import{$ as ae,Aa as d,Ba as p,Ca as u,Da as C,E as $,Ga as k,Ha as V,I as f,Ia as _,Ja as A,Ka as g,M as y,N as P,O as ee,R as ie,Ta as le,Ua as w,V as oe,Va as l,W as M,Wa as h,Xa as F,Ya as se,ca as re,cb as pe,da as te,ea as o,ka as x,lb as D,ob as B,pb as E,qa as S,ra as c,sa as m,va as T,wa as j,wb as de,xa as v,ya as a,za as r,zb as R}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var be=[{path:"",pathMatch:"full",redirectTo:"dashboard"},{path:"dashboard",loadComponent:()=>import("./chunk-ZG7H3XPL.js").then(e=>e.Dashboard),data:{nav:"dashboard",title:"Dashboard"}},{path:"graph",loadComponent:()=>import("./chunk-ONKHTXHJ.js").then(e=>e.Graph),data:{nav:"graph",title:"Graph"}},{path:"specs",loadComponent:()=>import("./chunk-PDTQX2UL.js").then(e=>e.Specs),data:{nav:"specs",title:"Specs"}},{path:"drift",loadComponent:()=>import("./chunk-P5JX67LT.js").then(e=>e.Drift),data:{nav:"drift",title:"Drift queue"}},{path:"improvements",loadComponent:()=>import("./chunk-JBO7ZIPO.js").then(e=>e.Improvements),data:{nav:"improvements",title:"Improvements"}},{path:"maintainability",loadComponent:()=>import("./chunk-JQXCRIK2.js").then(e=>e.Maintainability),data:{nav:"maintainability",title:"Maintainability"}},{path:"domain",loadComponent:()=>import("./chunk-EZZBWC7Z.js").then(e=>e.Domain),data:{nav:"domain",title:"Domain"}},{path:"workflows",loadComponent:()=>import("./chunk-Z5L3T5EO.js").then(e=>e.Workflows),data:{nav:"workflows",title:"Workflows"}},{path:"runs",loadComponent:()=>import("./chunk-IZQXYQNQ.js").then(e=>e.Runs),data:{nav:"runs",title:"Runs"}},{path:"runs/:id",loadComponent:()=>import("./chunk-ITHLF4GI.js").then(e=>e.RunDetail),data:{nav:"runs",title:"Run detail"}},{path:"chat",loadComponent:()=>import("./chunk-L37MTFSG.js").then(e=>e.Chat),data:{nav:"chat",title:"Chat"}},{path:"sessions",loadComponent:()=>import("./chunk-JT2YIHPL.js").then(e=>e.Sessions),data:{nav:"sessions",title:"Sessions"}},{path:"sessions/:id",loadComponent:()=>import("./chunk-XWDR6MPC.js").then(e=>e.SessionDetail),data:{nav:"sessions",title:"Session detail"}},{path:"heatmap",loadComponent:()=>import("./chunk-YAMRN47K.js").then(e=>e.Heatmap),data:{nav:"heatmap",title:"Heatmap"}},{path:"costs",loadComponent:()=>import("./chunk-WCHGDXWC.js").then(e=>e.Costs),data:{nav:"costs",title:"Costs"}},{path:"specship-impact",loadComponent:()=>import("./chunk-TQ3P2QZO.js").then(e=>e.SpecshipImpact),data:{nav:"specship-impact",title:"SpecShip Impact"}},{path:"compare",loadComponent:()=>import("./chunk-WCKHQIYN.js").then(e=>e.Compare),data:{nav:"compare",title:"Compare projects"}},{path:"tips",loadComponent:()=>import("./chunk-A5R3MJMO.js").then(e=>e.Tips),data:{nav:"tips",title:"Tips"}},{path:"memory",loadComponent:()=>import("./chunk-45QHGCB4.js").then(e=>e.Memory),data:{nav:"memory",title:"Memory"}},{path:"design",loadComponent:()=>import("./chunk-WAI2JMZP.js").then(e=>e.Design),data:{nav:"design",title:"Design system"}},{path:"settings",loadComponent:()=>import("./chunk-TPDB5GJN.js").then(e=>e.Settings),data:{nav:"settings",title:"Settings"}},{path:"**",redirectTo:"dashboard"}];var _e={providers:[oe(),ge(be)]};function xe(e,n){e&1&&(ee(),C(0,"rect",14)(1,"rect",15))}var q=class e{size=E(24);tile=E(!0);glow=E(!0);static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-logo-mark"]],inputs:{size:[1,"size"],tile:[1,"tile"],glow:[1,"glow"]},decls:16,vars:5,consts:[["viewBox","0 0 32 32","fill","none",2,"flex-shrink","0"],["id","ssTile","x1","0","y1","0","x2","32","y2","32","gradientUnits","userSpaceOnUse"],["stop-color","#12161E"],["offset","1","stop-color","#0B0D11"],["id","ssLead","x1","18","y1","11","x2","26","y2","21","gradientUnits","userSpaceOnUse"],["stop-color","#6FA0F6"],["offset","1","stop-color","#5B93F2"],["transform","translate(4.6 4.6) scale(0.715)"],["d","M5 16 H11 M11 9 L23 16 L11 23","stroke","rgba(150,165,200,0.5)","stroke-width","1.9","stroke-linecap","round","stroke-linejoin","round","fill","none"],["x1","11","y1","9","x2","11","y2","23","stroke","rgba(150,165,200,0.4)","stroke-width","1.9","stroke-linecap","round"],["cx","23","cy","16","r","3.6","fill","url(#ssLead)"],["cx","11","cy","9","r","2.9","fill","#A586F5"],["cx","11","cy","23","r","2.9","fill","#46C26B"],["cx","5","cy","16","r","2.1","fill","#29D2BE"],["width","32","height","32","rx","7.2","fill","url(#ssTile)"],["x","0.5","y","0.5","width","31","height","31","rx","6.7","fill","none","stroke","rgba(255,255,255,0.08)"]],template:function(t,i){t&1&&(ee(),p(0,"svg",0)(1,"defs")(2,"linearGradient",1),C(3,"stop",2)(4,"stop",3),u(),p(5,"linearGradient",4),C(6,"stop",5)(7,"stop",6),u()(),c(8,xe,2,0),p(9,"g",7),C(10,"path",8)(11,"line",9)(12,"circle",10)(13,"circle",11)(14,"circle",12)(15,"circle",13),u()()),t&2&&(le("filter",i.glow()?"drop-shadow(0 0 9px rgba(91,147,242,0.35))":"none"),S("width",i.size())("height",i.size()),o(8),m(i.tile()?8:-1))},styles:["[_nghost-%COMP%]{display:inline-flex;align-items:center;justify-content:center;line-height:0}"],changeDetection:0})};var Ce=e=>["/",e],ye=(e,n)=>n.group,Pe=(e,n)=>n.id;function ke(e,n){e&1&&(a(0,"div",3),l(1,"SpecShip "),a(2,"span",14),l(3,"Desktop"),r()())}function we(e,n){if(e&1&&(a(0,"div",15),l(1),r()),e&2){let t=g().$implicit;o(),h(t.group)}}function Me(e,n){if(e&1&&(a(0,"span",18),l(1),r()),e&2){let t=g(2).$implicit,i=g(2);S("data-kind",t.badgeKind),o(),h(i.badgeOf(t))}}function Se(e,n){if(e&1&&(a(0,"span",11),l(1),r(),c(2,Me,2,2,"span",18)),e&2){let t=g().$implicit,i=g(2);o(),h(t.label),o(),m(i.badgeOf(t)>0?2:-1)}}function Ee(e,n){if(e&1&&(a(0,"a",16),d(1,"span",8),a(2,"span",9),d(3,"app-icon",17),r(),c(4,Se,3,2),r()),e&2){let t=n.$implicit,i=g(2);v("routerLink",pe(5,Ce,t.id))("title",i.collapsed()?t.label:null),o(3),v("name",t.icon)("size",16),o(),m(i.collapsed()?-1:4)}}function Oe(e,n){if(e&1&&(a(0,"div",5),c(1,we,2,1,"div",15),T(2,Ee,5,7,"a",16,Pe),r()),e&2){let t=n.$implicit,i=g();o(),m(i.collapsed()?-1:1),o(),j(t.items)}}function Te(e,n){e&1&&(a(0,"span",11),l(1,"Design system"),r())}function je(e,n){e&1&&(a(0,"span",11),l(1,"Settings"),r())}var K=class e{collapsed=E(!1);api=f(H);projects=f(I);status=L(this.api,()=>`/api/status${this.projects.projectQuery()}`);tips=L(this.api,()=>"/api/claude/tips");improvements=L(this.api,()=>"/api/reflect?state=open");nav=[{group:"Project",items:[{id:"dashboard",label:"Dashboard",icon:"dashboard"},{id:"graph",label:"Graph",icon:"graph"},{id:"specs",label:"Specs",icon:"book"},{id:"domain",label:"Domain",icon:"layers"},{id:"drift",label:"Drift queue",icon:"drift",badge:()=>this.status.state().data?.drift??0,badgeKind:"warn"},{id:"maintainability",label:"Maintainability",icon:"wrench"},{id:"improvements",label:"Improvements",icon:"sparkles",badge:()=>(this.improvements.state().data?.proposals??[]).filter(n=>n.severity==="high").length,badgeKind:"error"},{id:"workflows",label:"Workflows",icon:"workflow"},{id:"runs",label:"Runs",icon:"play"},{id:"chat",label:"Chat",icon:"chat"}]},{group:"Claude Code",items:[{id:"sessions",label:"Sessions",icon:"sessions"},{id:"heatmap",label:"Heatmap",icon:"heatmap"},{id:"costs",label:"Costs",icon:"dollar"},{id:"specship-impact",label:"SpecShip Impact",icon:"graph"},{id:"compare",label:"Compare projects",icon:"compare"},{id:"memory",label:"Memory",icon:"memory"},{id:"tips",label:"Tips",icon:"tips",badge:()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity!=="info").length,badgeKind:"error"}]}];badgeOf(n){return n.badge?n.badge():0}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-sidebar"]],inputs:{collapsed:[1,"collapsed"]},decls:18,vars:10,consts:[[1,"sidebar"],[1,"brand"],[3,"size"],[1,"brand-text"],[1,"scroll-y","nav-scroll"],[1,"nav-group"],[1,"pinned"],["routerLink","/design","routerLinkActive","active",1,"nav-item",3,"title"],[1,"indicator"],[1,"nav-icon"],["name","palette",3,"size"],[1,"nav-label"],["routerLink","/settings","routerLinkActive","active",1,"nav-item",3,"title"],["name","settings",3,"size"],[1,"muted"],[1,"eyebrow","group-label"],["routerLinkActive","active",1,"nav-item",3,"routerLink","title"],[3,"name","size"],[1,"badge"]],template:function(t,i){t&1&&(a(0,"nav",0)(1,"div",1),d(2,"app-logo-mark",2),c(3,ke,4,0,"div",3),r(),a(4,"div",4),T(5,Oe,4,1,"div",5,ye),r(),a(7,"div",6)(8,"a",7),d(9,"span",8),a(10,"span",9),d(11,"app-icon",10),r(),c(12,Te,2,0,"span",11),r(),a(13,"a",12),d(14,"span",8),a(15,"span",9),d(16,"app-icon",13),r(),c(17,je,2,0,"span",11),r()()()),t&2&&(w("collapsed",i.collapsed()),o(2),v("size",26),o(),m(i.collapsed()?-1:3),o(2),j(i.nav),o(3),v("title",i.collapsed()?"Design system":null),o(3),v("size",16),o(),m(i.collapsed()?-1:12),o(),v("title",i.collapsed()?"Settings":null),o(3),v("size",16),o(),m(i.collapsed()?-1:17))},dependencies:[me,ue,R,q],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.sidebar[_ngcontent-%COMP%]{width:var(--sidebar-w);flex-shrink:0;background:var(--bg-panel);border-right:1px solid var(--border-subtle);display:flex;flex-direction:column;transition:width .12s;overflow:hidden;font-family:var(--font-ui)}.sidebar.collapsed[_ngcontent-%COMP%]{width:var(--sidebar-w-collapsed)}.brand[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:15px 16px}.collapsed[_ngcontent-%COMP%] .brand[_ngcontent-%COMP%]{justify-content:center;padding:14px 0}.brand-text[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px;letter-spacing:-.01em}.brand-text[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted);font-weight:400}.nav-scroll[_ngcontent-%COMP%]{flex:1;padding:4px 8px}.nav-group[_ngcontent-%COMP%]{margin-bottom:10px}.group-label[_ngcontent-%COMP%]{padding:8px 8px 4px}.nav-item[_ngcontent-%COMP%]{position:relative;display:flex;align-items:center;gap:10px;height:32px;padding:0 10px;border-radius:7px;text-decoration:none;margin-bottom:1px;color:var(--text-secondary);font-weight:450;font-size:13px;transition:background .1s}.collapsed[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%]{padding:0;justify-content:center}.nav-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%]{background:var(--bg-active);color:var(--text-primary);font-weight:600}.nav-item.active[_ngcontent-%COMP%] .indicator[_ngcontent-%COMP%]{position:absolute;left:0;top:7px;bottom:7px;width:2.5px;border-radius:2px;background:var(--accent)}.nav-icon[_ngcontent-%COMP%]{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--text-secondary)}.nav-item[_ngcontent-%COMP%]:hover .nav-icon[_ngcontent-%COMP%]{color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%] .nav-icon[_ngcontent-%COMP%]{color:var(--accent)}.nav-label[_ngcontent-%COMP%]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.badge[_ngcontent-%COMP%]{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10px;font-weight:700;padding:1px 6px;min-width:18px;border-radius:999px;display:inline-flex;justify-content:center;color:var(--text-secondary);background:#ffffff0f}.badge[data-kind=error][_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.badge[data-kind=warn][_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pinned[_ngcontent-%COMP%]{padding:8px;border-top:1px solid var(--border-subtle)}'],changeDetection:0})};function De(e,n){if(e&1&&(p(0,"span",8),l(1),u(),C(2,"span",1),p(3,"span",9)(4,"span",10),l(5,"nodes"),u(),p(6,"span",4),l(7),u()(),p(8,"span",9)(9,"span",10),l(10,"edges"),u(),p(11,"span",4),l(12),u()(),C(13,"span",1),p(14,"span",9)(15,"span",10),l(16,"drift"),u(),p(17,"span",4),l(18),u()(),C(19,"span",11),p(20,"span",9)(21,"span",10),l(22,"indexed"),u(),p(23,"span",4),l(24),u()()),e&2){let t=g(),i=t.status.state().data;o(),h(i.projectPath),o(6),h(i.nodeCount.toLocaleString()),o(5),h(i.edgeCount.toLocaleString()),o(5),w("warn",i.drift>0)("success",i.drift===0),o(),h(i.drift),o(6),h(t.indexedLabel())}}function ze(e,n){e&1&&(p(0,"span",12),l(1,"loading status\u2026"),u(),C(2,"span",11))}function Ie(e,n){if(e&1&&(p(0,"span",12),l(1),u(),C(2,"span",11)),e&2){let t=g();o(),h(t.conn.online()?"no backend":"offline \u2014 no cached data")}}function Le(e,n){e&1&&(p(0,"span",5),l(1),u()),e&2&&(o(),F("\xB7 ",n))}function Re(e,n){e&1&&(p(0,"span",6),l(1,"\u26A0"),u()),e&2&&V("title",n)}var W=class e{api=f(H);projects=f(I);refreshSvc=f(ve);conn=f(fe);status=L(this.api,()=>`/api/status${this.projects.projectQuery()}`);offlineAge=D(()=>{let n=this.status.state().cachedAt??this.conn.lastOnlineAt();if(n===null)return null;let t=Date.now()-n;return t<1e4?"just now":t<6e4?`${Math.round(t/1e3)}s ago`:t<36e5?`${Math.round(t/6e4)}m ago`:t<864e5?`${Math.round(t/36e5)}h ago`:`${Math.round(t/864e5)}d ago`});indexedLabel=D(()=>{let n=this.status.state().data?.lastIndexed;if(!n)return"never";try{let t=new Date(n),i=Date.now()-t.getTime();return i<6e4?"just now":i<36e5?`${Math.round(i/6e4)}m ago`:i<864e5?`${Math.round(i/36e5)}h ago`:t.toLocaleDateString()}catch{return String(n)}});async refresh(){await this.refreshSvc.triggerGlobalRefresh()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-status-strip"]],decls:13,vars:14,consts:[[1,"status-strip"],[1,"divider"],[1,"seg","conn",3,"title"],[1,"conn-dot"],[1,"mono","val"],[1,"muted","conn-age"],[1,"refresh-error","mono",3,"title"],[1,"refresh",3,"click","disabled","title"],[1,"seg","mono"],[1,"seg"],[1,"lbl"],[1,"grow"],[1,"mono","muted"]],template:function(t,i){if(t&1&&(p(0,"div",0),c(1,De,25,9)(2,ze,3,0)(3,Ie,3,1),C(4,"span",1),p(5,"span",2),C(6,"span",3),p(7,"span",4),l(8),u(),c(9,Le,2,1,"span",5),u(),c(10,Re,2,1,"span",6),p(11,"button",7),A("click",function(){return i.refresh()}),l(12,"\u21BB"),u()()),t&2){let s,b;o(),m(i.status.state().data?1:i.status.state().loading?2:3),o(4),V("title",i.conn.online()?"Connected to the SpecShip server":"Server unreachable \u2014 showing the last cached data"),o(),w("live",i.conn.online())("off",!i.conn.online()),o(2),h(i.conn.online()?"Live":"Offline"),o(),m((s=!i.conn.online()&&i.offlineAge())?9:-1,s),o(),m((b=i.refreshSvc.error())?10:-1,b),o(),w("spinning",i.refreshSvc.loading()),V("disabled",i.refreshSvc.loading()||!i.conn.online())("title",i.conn.online()?i.refreshSvc.loading()?"Refreshing\u2026":"Refresh: sync index + re-ingest Claude Code transcripts. Updates Sessions, Heatmap, Costs, Memory, Drift, Graph.":"Offline \u2014 reconnect to refresh"),S("aria-label",i.conn.online()?i.refreshSvc.loading()?"Refreshing\u2026":"Refresh everything \u2014 sync index + ingest Claude Code transcripts":"Offline \u2014 reconnect to refresh")}},styles:["[_nghost-%COMP%]{display:contents}.status-strip[_ngcontent-%COMP%]{height:var(--status-h);flex-shrink:0;display:flex;align-items:center;gap:14px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel-2);font-size:11.5px;overflow:hidden;white-space:nowrap}.seg[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;flex-shrink:0}.lbl[_ngcontent-%COMP%]{color:var(--text-muted);font-size:11px}.val[_ngcontent-%COMP%]{color:var(--text-secondary);font-variant-numeric:tabular-nums}.val.warn[_ngcontent-%COMP%]{color:var(--warn)}.val.success[_ngcontent-%COMP%]{color:var(--success)}.divider[_ngcontent-%COMP%]{width:1px;height:12px;background:var(--border-subtle);flex-shrink:0}.grow[_ngcontent-%COMP%]{flex:1}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.refresh[_ngcontent-%COMP%]{background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:14px;padding:2px 6px;border-radius:4px;transition:background .12s,color .12s}.refresh[_ngcontent-%COMP%]:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}.refresh[_ngcontent-%COMP%]:disabled{cursor:progress;opacity:.8}.refresh[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.refresh.spinning[_ngcontent-%COMP%]{display:inline-block;animation:_ngcontent-%COMP%_spin .9s linear infinite;color:var(--accent)}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.refresh-error[_ngcontent-%COMP%]{color:var(--warn);font-size:12px;padding:0 2px;cursor:help}.conn[_ngcontent-%COMP%]{gap:5px}.conn-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.conn-dot.live[_ngcontent-%COMP%]{background:var(--success);box-shadow:0 0 6px var(--success)}.conn-dot.off[_ngcontent-%COMP%]{background:var(--warn);box-shadow:0 0 6px var(--warn)}.conn-age[_ngcontent-%COMP%]{font-size:11px}"],changeDetection:0})};var Ne=(e,n)=>n.slug;function Ae(e,n){e&1&&d(0,"span",8)}function Fe(e,n){e&1&&d(0,"span",9)}function Be(e,n){e&1&&d(0,"span",10)}function $e(e,n){if(e&1&&(a(0,"span",7),l(1),r(),c(2,Ae,1,0,"span",8)(3,Fe,1,0,"span",9)(4,Be,1,0,"span",10)),e&2){let t=n,i=g();o(),h(i.shortPath(t.path)),o(),m(t.exists?t.initialized?4:3:2)}}function Ve(e,n){e&1&&(a(0,"span",3),l(1,"Select project"),r())}function He(e,n){if(e&1){let t=k();a(0,"button",20),_("click",function(){y(t);let s=g(2);return P(s.clear())}),d(1,"app-icon",21),l(2," Clear "),r()}e&2&&(o(),v("size",11))}function Ge(e,n){e&1&&(a(0,"span",16),l(1,"\xB7 loading\u2026"),r())}function qe(e,n){if(e&1&&(a(0,"span",16),l(1),r()),e&2){let t=g(2);o(),F("\xB7 ",t.filtered().length," shown \xB7 live")}}function Ke(e,n){e&1&&(a(0,"div",18),l(1,"No projects match."),r())}function We(e,n){e&1&&(a(0,"span",25),l(1,"missing"),r())}function Ue(e,n){e&1&&(a(0,"span",26),l(1,"not init"),r())}function Qe(e,n){e&1&&(a(0,"span",27),l(1,"initialized"),r())}function Je(e,n){if(e&1&&(a(0,"span"),l(1),r()),e&2){let t=g().$implicit,i=g(2);o(),F("\xB7 ",i.formatRelative(t.lastModifiedMs))}}function Ye(e,n){e&1&&d(0,"app-icon",29),e&2&&v("size",13)}function Xe(e,n){if(e&1){let t=k();a(0,"button",22),_("click",function(){let s=y(t).$implicit,b=g(2);return P(b.pick(s.slug))}),a(1,"div",23)(2,"div",24)(3,"span",7),l(4),r(),c(5,We,2,0,"span",25)(6,Ue,2,0,"span",26)(7,Qe,2,0,"span",27),r(),a(8,"div",28)(9,"span"),l(10),r(),c(11,Je,2,1,"span"),r()(),c(12,Ye,1,1,"app-icon",29),r()}if(e&2){let t=n.$implicit,i=g(2);w("active",i.projects.activeSlug()===t.slug),o(4),h(i.shortPath(t.path)),o(),m(t.exists?t.initialized?7:6:5),o(5),se("",t.sessionCount," session",t.sessionCount===1?"":"s"),o(),m(t.lastModifiedMs>0?11:-1),o(),m(i.projects.activeSlug()===t.slug?12:-1)}}function Ze(e,n){if(e&1){let t=k();a(0,"div",6)(1,"div",11),d(2,"app-icon",12),a(3,"input",13),_("input",function(s){y(t);let b=g();return P(b.onQuery(s.target.value))}),r(),c(4,He,3,1,"button",14),r(),a(5,"div",15)(6,"span"),l(7),r(),c(8,Ge,2,0,"span",16)(9,qe,2,1,"span",16),r(),a(10,"div",17),c(11,Ke,2,0,"div",18),T(12,Xe,13,8,"button",19,Ne),r()()}if(e&2){let t=g();o(2),v("size",13),o(),v("value",t.query()),o(),m(t.projects.activeSlug()?4:-1),o(3),h(t.projects.claudeRoot()??"~/.claude/projects"),o(),m(t.projects.loading()?8:9),o(3),m(t.filtered().length===0&&!t.projects.loading()?11:-1),o(),j(t.filtered())}}var U=class e{host=f(ae);projects=f(I);open=M(!1);query=M("");filtered=D(()=>{let n=this.query().trim().toLowerCase(),t=this.projects.projects();return n?t.filter(i=>i.path.toLowerCase().includes(n)||i.slug.toLowerCase().includes(n)):t});badge=D(()=>this.projects.projects().length);toggle(){this.open.update(n=>!n)}pick(n){this.projects.setActive(n),this.open.set(!1),this.query.set("")}clear(){this.projects.setActive(null),this.open.set(!1)}onQuery(n){this.query.set(n)}onDocumentClick(n){if(!this.open())return;let t=n.target;t&&!this.host.nativeElement.contains(t)&&this.open.set(!1)}onEscape(){this.open()&&this.open.set(!1)}formatRelative(n){if(!n)return"";let t=Date.now()-n,i=Math.round(t/1e3);if(i<60)return`${i}s ago`;let s=Math.round(i/60);if(s<60)return`${s}m ago`;let b=Math.round(s/60);if(b<24)return`${b}h ago`;let ne=Math.round(b/24);return ne<30?`${ne}d ago`:new Date(n).toLocaleDateString()}shortPath(n){if(!n)return"";let t=this.detectHome();return t&&n===t?"~":t&&n.startsWith(t+"/")?"~/"+n.slice(t.length+1):n}detectHome(){let n=this.projects.claudeRoot();if(!n)return null;let t="/.claude/projects";return n.endsWith(t)?n.slice(0,-t.length):null}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-project-picker"]],hostBindings:function(t,i){t&1&&_("click",function(b){return i.onDocumentClick(b)},te)("keydown.escape",function(){return i.onEscape()},te)},decls:9,vars:9,consts:[[1,"wrap"],["type","button","aria-label","Switch project",1,"trigger",3,"click"],["name","folder",3,"size"],[1,"placeholder"],[1,"badge","mono"],[3,"name","size"],["role","dialog","aria-label","Pick a project",1,"popover"],[1,"path","mono"],["title","path no longer exists on disk",1,"status-dot","missing"],["title","not yet specship init'd",1,"status-dot","warn"],["title","initialized",1,"status-dot","ok"],[1,"popover-head","row","gap-8"],["name","search",3,"size"],["type","text","placeholder","Filter projects\u2026","autofocus","",1,"popover-input",3,"input","value"],["title","Clear selection",1,"btn","btn-ghost","btn-xs"],[1,"popover-meta","mono"],[1,"muted"],[1,"popover-list","scroll-y"],[1,"empty"],["type","button",1,"row-item",3,"active"],["title","Clear selection",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],["type","button",1,"row-item",3,"click"],[1,"col","gap-2","grow"],[1,"row","gap-6","path-line"],[1,"pill","missing"],[1,"pill","warn"],[1,"pill","ok"],[1,"meta","row","gap-8","mono","muted"],["name","check",3,"size"]],template:function(t,i){if(t&1&&(a(0,"div",0)(1,"button",1),_("click",function(){return i.toggle()}),d(2,"app-icon",2),c(3,$e,5,2)(4,Ve,2,0,"span",3),a(5,"span",4),l(6),r(),d(7,"app-icon",5),r(),c(8,Ze,14,6,"div",6),r()),t&2){let s;w("open",i.open()),o(),S("aria-expanded",i.open()),o(),v("size",13),o(),m((s=i.projects.active())?3:4,s),o(3),h(i.badge()),o(),v("name",i.open()?"chevronDown":"chevronRight")("size",11),o(),m(i.open()?8:-1)}},dependencies:[R],styles:["[_nghost-%COMP%]{display:inline-flex;min-width:0}.wrap[_ngcontent-%COMP%]{position:relative;min-width:0}.trigger[_ngcontent-%COMP%]{height:30px;padding:0 11px 0 10px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;color:var(--text-secondary);display:inline-flex;align-items:center;gap:8px;font-family:var(--font-ui);font-size:12.5px;cursor:pointer;max-width:360px;min-width:0;transition:background .1s,border-color .1s}.trigger[_ngcontent-%COMP%]:hover, .wrap.open[_ngcontent-%COMP%] .trigger[_ngcontent-%COMP%]{background:var(--bg-panel-2);border-color:var(--border-strong);color:var(--text-primary)}.trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.trigger[_ngcontent-%COMP%]:hover app-icon[_ngcontent-%COMP%]{color:var(--text-secondary)}.path[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.placeholder[_ngcontent-%COMP%]{color:var(--text-muted);font-style:italic}.status-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.status-dot.ok[_ngcontent-%COMP%]{background:var(--success)}.status-dot.warn[_ngcontent-%COMP%]{background:var(--warn)}.status-dot.missing[_ngcontent-%COMP%]{background:var(--error)}.badge[_ngcontent-%COMP%]{font-size:10px;padding:1px 6px;border-radius:999px;background:var(--bg-active);color:var(--text-muted);font-variant-numeric:tabular-nums;flex-shrink:0}.popover[_ngcontent-%COMP%]{position:absolute;top:calc(100% + 6px);left:0;z-index:30;width:420px;max-width:calc(100vw - 40px);background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:10px;box-shadow:var(--shadow-pop);display:flex;flex-direction:column;max-height:480px;animation:_ngcontent-%COMP%_pp-in .12s ease-out}@keyframes _ngcontent-%COMP%_pp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.popover-head[_ngcontent-%COMP%]{padding:10px 12px 8px;border-bottom:1px solid var(--border-subtle)}.popover-head[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.popover-input[_ngcontent-%COMP%]{flex:1;min-width:0;background:transparent;border:none;outline:none;font-family:var(--font-ui);font-size:13px;color:var(--text-primary)}.popover-input[_ngcontent-%COMP%]::placeholder{color:var(--text-muted)}.popover-meta[_ngcontent-%COMP%]{padding:6px 12px 8px;font-size:10.5px;color:var(--text-secondary);border-bottom:1px solid var(--border-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.popover-meta[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted)}.popover-list[_ngcontent-%COMP%]{flex:1;min-height:0;padding:4px}.row-item[_ngcontent-%COMP%]{width:100%;display:flex;align-items:center;gap:10px;padding:9px 10px;border:none;border-radius:7px;background:transparent;color:inherit;cursor:pointer;font-family:inherit;text-align:left;transition:background 80ms}.row-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.row-item.active[_ngcontent-%COMP%]{background:var(--accent-soft);color:var(--text-primary)}.row-item.active[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--accent)}.path-line[_ngcontent-%COMP%]{min-width:0}.path-line[_ngcontent-%COMP%] .path[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta[_ngcontent-%COMP%]{font-size:10.5px}.pill[_ngcontent-%COMP%]{font-size:10px;font-weight:600;padding:1px 7px;border-radius:999px;white-space:nowrap;flex-shrink:0}.pill.ok[_ngcontent-%COMP%]{color:var(--success);background:var(--success-soft)}.pill.warn[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pill.missing[_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.empty[_ngcontent-%COMP%]{text-align:center;color:var(--text-muted);font-size:12px;padding:18px 12px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1;min-width:0}.row[_ngcontent-%COMP%]{display:flex;align-items:center}.col[_ngcontent-%COMP%]{display:flex;flex-direction:column}.gap-2[_ngcontent-%COMP%]{gap:2px}.gap-6[_ngcontent-%COMP%]{gap:6px}.gap-8[_ngcontent-%COMP%]{gap:8px}.scroll-y[_ngcontent-%COMP%]{overflow-y:auto;overflow-x:hidden}"],changeDetection:0})};var Q=class e{deferred=null;canInstall=M(!1);constructor(){typeof window>"u"||window.matchMedia?.("(display-mode: standalone)").matches===!0||window.navigator.standalone===!0||(window.addEventListener("beforeinstallprompt",t=>{t.preventDefault(),this.deferred=t,this.canInstall.set(!0)}),window.addEventListener("appinstalled",()=>{this.deferred=null,this.canInstall.set(!1)}))}async install(){let n=this.deferred;if(n){this.deferred=null,this.canInstall.set(!1);try{await n.prompt(),await n.userChoice}catch{}}}static \u0275fac=function(t){return new(t||e)};static \u0275prov=$({token:e,factory:e.\u0275fac,providedIn:"root"})};function et(e,n){if(e&1){let t=k();a(0,"button",9),_("click",function(){y(t);let s=g();return P(s.onInstall())}),d(1,"app-icon",10),a(2,"span"),l(3,"Install"),r()()}e&2&&(o(),v("size",14))}var J=class e{toggleSidebar=B();openPalette=B();theme=f(G);effective=this.theme.effective;pwa=f(Q);onToggleTheme(){this.theme.toggle()}onMenuClick(){this.toggleSidebar.emit()}onPalette(){this.openPalette.emit()}onInstall(){this.pwa.install()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-top-bar"]],outputs:{toggleSidebar:"toggleSidebar",openPalette:"openPalette"},decls:14,vars:6,consts:[[1,"topbar"],["title","Toggle sidebar","aria-label","Toggle sidebar",1,"ghost","icon-btn",3,"click"],["name","menu",3,"size"],["aria-label","Open command palette",1,"palette-trigger",3,"click"],["name","search",3,"size"],[1,"grow"],["title","Install SpecShip as an app","aria-label","Install SpecShip as an app",1,"ghost",2,"display","inline-flex","align-items","center","gap","6px","padding","0 10px","height","30px","font-size","12px"],["aria-label","Toggle theme",1,"ghost","icon-btn",3,"click","title"],[3,"name","size"],["title","Install SpecShip as an app","aria-label","Install SpecShip as an app",1,"ghost",2,"display","inline-flex","align-items","center","gap","6px","padding","0 10px","height","30px","font-size","12px",3,"click"],["name","plus",3,"size"]],template:function(t,i){t&1&&(a(0,"div",0)(1,"button",1),_("click",function(){return i.onMenuClick()}),d(2,"app-icon",2),r(),d(3,"app-project-picker"),a(4,"button",3),_("click",function(){return i.onPalette()}),d(5,"app-icon",4),a(6,"span"),l(7,"Search or jump to\u2026"),r(),a(8,"kbd"),l(9,"\u2318K"),r()(),d(10,"span",5),c(11,et,4,1,"button",6),a(12,"button",7),_("click",function(){return i.onToggleTheme()}),d(13,"app-icon",8),r()()),t&2&&(o(2),v("size",16),o(3),v("size",13),o(6),m(i.pwa.canInstall()?11:-1),o(),v("title","Theme: "+i.effective()),o(),v("name",i.effective()==="dark"?"sun":"moon")("size",16))},dependencies:[R,U],styles:["[_nghost-%COMP%]{display:contents}.topbar[_ngcontent-%COMP%]{height:44px;flex-shrink:0;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-canvas)}.ghost[_ngcontent-%COMP%]{background:transparent;border:1px solid transparent;color:var(--text-secondary);cursor:pointer}.ghost[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.icon-btn[_ngcontent-%COMP%]{padding:6px 9px;border-radius:5px;font-size:16px}.palette-trigger[_ngcontent-%COMP%]{flex:1;max-width:380px;height:30px;padding:0 11px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;cursor:text;color:var(--text-muted);font-size:12.5px;text-align:left;display:flex;align-items:center;gap:8px}.palette-trigger[_ngcontent-%COMP%]:hover{border-color:var(--border-strong);color:var(--text-secondary)}.palette-trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted)}.palette-trigger[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{flex:1}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}.grow[_ngcontent-%COMP%]{flex:1}"],changeDetection:0})};var tt=(e,n)=>n.id;function nt(e,n){if(e&1){let t=k();p(0,"button",6),A("click",function(){let s=y(t).$implicit,b=g(2);return P(b.go(s.id))}),p(1,"span",7),l(2),u(),p(3,"span",8),l(4),u()()}if(e&2){let t=n.$implicit;o(2),h(t.label),o(2),h(t.sub)}}function it(e,n){if(e&1){let t=k();p(0,"div",1),A("click",function(s){y(t);let b=g();return P(b.onBackdrop(s))}),p(1,"div",2)(2,"div",3)(3,"span"),l(4,"Jump to\u2026"),u(),p(5,"kbd"),l(6,"esc"),u()(),p(7,"div",4),T(8,nt,5,2,"button",5,tt),u()()()}if(e&2){let t=g();o(8),j(t.items)}}var ot=[{id:"dashboard",label:"Dashboard",sub:"/dashboard"},{id:"graph",label:"Graph",sub:"/graph"},{id:"specs",label:"Specs",sub:"/specs"},{id:"drift",label:"Drift queue",sub:"/drift"},{id:"workflows",label:"Workflows",sub:"/workflows"},{id:"runs",label:"Runs",sub:"/runs"},{id:"chat",label:"Chat",sub:"/chat"},{id:"sessions",label:"Sessions",sub:"/sessions"},{id:"heatmap",label:"Heatmap",sub:"/heatmap"},{id:"costs",label:"Costs",sub:"/costs"},{id:"compare",label:"Compare projects",sub:"/compare"},{id:"tips",label:"Tips",sub:"/tips"},{id:"settings",label:"Settings",sub:"/settings"}],Y=class e{open=E(!1);close=B();router=f(z);items=ot;go(n){this.router.navigate(["/"+n]),this.close.emit()}onBackdrop(n){n.target===n.currentTarget&&this.close.emit()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-command-palette"]],inputs:{open:[1,"open"]},outputs:{close:"close"},decls:1,vars:1,consts:[[1,"backdrop"],[1,"backdrop",3,"click"],[1,"palette"],[1,"palette-header"],[1,"palette-list","scroll-y"],[1,"item"],[1,"item",3,"click"],[1,"label"],[1,"sub","mono"]],template:function(t,i){t&1&&c(0,it,10,0,"div",0),t&2&&m(i.open()?0:-1)},styles:["[_nghost-%COMP%]{display:contents}.backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:grid;place-items:start center;padding-top:12vh;z-index:100;animation:fadeIn .1s}.palette[_ngcontent-%COMP%]{width:560px;max-width:90vw;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-pop);overflow:hidden}.palette-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:12px 14px;border-bottom:1px solid var(--border-subtle);font-size:13px}.palette-list[_ngcontent-%COMP%]{max-height:380px;padding:6px}.item[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:7px;cursor:pointer;color:var(--text-primary);font-family:inherit;font-size:13px;text-align:left}.item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.label[_ngcontent-%COMP%]{flex:1}.sub[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted)}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}"],changeDetection:0})};var X=class e{es=null;notify=f(he);router=f(z);start(){if(!(this.es||typeof EventSource>"u")){try{this.es=new EventSource("/api/events")}catch{return}this.es.onmessage=n=>{let t;try{t=JSON.parse(n.data)}catch{return}!t||t.kind!=="approval"&&t.kind!=="runDone"&&t.kind!=="drift"&&t.kind!=="reflect"||this.notify.notify(t.kind,t.title,{body:t.detail,tag:`${t.project}:${t.kind}:${t.id}`,onClick:()=>this.routeFor(t)})}}}stop(){this.es?.close(),this.es=null}routeFor(n){let t={project:n.project};n.kind==="drift"?this.router.navigate(["/drift"],{queryParams:t}):n.kind==="reflect"?this.router.navigate(["/improvements"],{queryParams:t}):this.router.navigate(["/runs",n.id],{queryParams:t})}static \u0275fac=function(t){return new(t||e)};static \u0275prov=$({token:e,factory:e.\u0275fac,providedIn:"root"})};var Z=class e{_theme=f(G);_destroyRef=f(ie);_router=f(z);_events=f(X);constructor(){this._events.start()}sidebarCollapsed=M(typeof window<"u"&&window.innerWidth<1100);paletteOpen=M(!1);gChord={armed:!1,t:0};onGlobalKey(n){let t=n.metaKey||n.ctrlKey;if(t&&n.key.toLowerCase()==="k"){n.preventDefault(),this.paletteOpen.update(i=>!i);return}if(n.key==="Escape"){this.paletteOpen.set(!1);return}if(!t&&n.key.toLowerCase()==="g"&&!this.gChord.armed){let i=n.target;if(i&&/input|textarea/i.test(i.tagName))return;this.gChord.armed=!0,this.gChord.t=Date.now(),setTimeout(()=>{this.gChord.armed=!1},600);return}if(this.gChord.armed&&!t){let i=n.key.toLowerCase();i==="d"?this._router.navigate(["/dashboard"]):i==="g"?this._router.navigate(["/graph"]):i==="s"&&this._router.navigate(["/specs"]),this.gChord.armed=!1}}toggleSidebar(){this.sidebarCollapsed.update(n=>!n)}onOpenPalette(){this.paletteOpen.set(!0)}onClosePalette(){this.paletteOpen.set(!1)}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-root"]],hostBindings:function(t,i){t&1&&_("keydown",function(b){return i.onGlobalKey(b)},re)},decls:8,vars:2,consts:[[1,"shell"],[3,"collapsed"],[1,"main"],[3,"toggleSidebar","openPalette"],[1,"page-frame"],[3,"close","open"]],template:function(t,i){t&1&&(a(0,"div",0),d(1,"app-sidebar",1),a(2,"div",2),d(3,"app-status-strip"),a(4,"app-top-bar",3),_("toggleSidebar",function(){return i.toggleSidebar()})("openPalette",function(){return i.onOpenPalette()}),r(),a(5,"div",4),d(6,"router-outlet"),r()(),a(7,"app-command-palette",5),_("close",function(){return i.onClosePalette()}),r()()),t&2&&(o(),v("collapsed",i.sidebarCollapsed()),o(6),v("open",i.paletteOpen()))},dependencies:[ce,K,W,J,Y],styles:["[_nghost-%COMP%]{display:block;height:100%}.shell[_ngcontent-%COMP%]{display:flex;height:100vh;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base)}.main[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.page-frame[_ngcontent-%COMP%]{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--bg-canvas)}"],changeDetection:0})};de(Z,_e).catch(e=>console.error(e));typeof navigator<"u"&&"serviceWorker"in navigator&&window.addEventListener("load",()=>{navigator.serviceWorker.register("sw.js").catch(e=>{console.warn("[specship] offline service worker registration failed",e)})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvakumaresra/specship",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
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",
@@ -1 +0,0 @@
1
- import{a as G,b as he}from"./chunk-Y6WWDS4R.js";import{a as fe,b as ve,c as L}from"./chunk-GR72OOCN.js";import{b as ce,c as z,d as me,e as ue,f as ge}from"./chunk-SHPTC4RL.js";import{a as I}from"./chunk-7RNS77UP.js";import{a as H}from"./chunk-E44X4RH2.js";import{$ as ae,Aa as d,Ba as p,Ca as u,Da as C,E as $,Ga as k,Ha as V,I as f,Ia as b,Ja as A,Ka as g,M as y,N as P,O as ee,R as ie,Ta as se,Ua as w,V as oe,Va as s,W as S,Wa as h,Xa as F,Ya as le,ca as re,cb as pe,da as te,ea as o,ka as x,lb as D,ob as B,pb as E,qa as M,ra as c,sa as m,va as T,wa as j,wb as de,xa as v,ya as a,za as r,zb as R}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var _e=[{path:"",pathMatch:"full",redirectTo:"dashboard"},{path:"dashboard",loadComponent:()=>import("./chunk-D5OCNEJA.js").then(e=>e.Dashboard),data:{nav:"dashboard",title:"Dashboard"}},{path:"graph",loadComponent:()=>import("./chunk-WLIMNDS3.js").then(e=>e.Graph),data:{nav:"graph",title:"Graph"}},{path:"specs",loadComponent:()=>import("./chunk-RJLLYZEQ.js").then(e=>e.Specs),data:{nav:"specs",title:"Specs"}},{path:"drift",loadComponent:()=>import("./chunk-FHZHD2ZG.js").then(e=>e.Drift),data:{nav:"drift",title:"Drift queue"}},{path:"improvements",loadComponent:()=>import("./chunk-JBO7ZIPO.js").then(e=>e.Improvements),data:{nav:"improvements",title:"Improvements"}},{path:"workflows",loadComponent:()=>import("./chunk-Z5L3T5EO.js").then(e=>e.Workflows),data:{nav:"workflows",title:"Workflows"}},{path:"runs",loadComponent:()=>import("./chunk-UBOZGQNK.js").then(e=>e.Runs),data:{nav:"runs",title:"Runs"}},{path:"runs/:id",loadComponent:()=>import("./chunk-ITHLF4GI.js").then(e=>e.RunDetail),data:{nav:"runs",title:"Run detail"}},{path:"chat",loadComponent:()=>import("./chunk-L37MTFSG.js").then(e=>e.Chat),data:{nav:"chat",title:"Chat"}},{path:"sessions",loadComponent:()=>import("./chunk-ASZ77FMZ.js").then(e=>e.Sessions),data:{nav:"sessions",title:"Sessions"}},{path:"sessions/:id",loadComponent:()=>import("./chunk-RASJHUXS.js").then(e=>e.SessionDetail),data:{nav:"sessions",title:"Session detail"}},{path:"heatmap",loadComponent:()=>import("./chunk-YAMRN47K.js").then(e=>e.Heatmap),data:{nav:"heatmap",title:"Heatmap"}},{path:"costs",loadComponent:()=>import("./chunk-WCHGDXWC.js").then(e=>e.Costs),data:{nav:"costs",title:"Costs"}},{path:"specship-impact",loadComponent:()=>import("./chunk-TQ3P2QZO.js").then(e=>e.SpecshipImpact),data:{nav:"specship-impact",title:"SpecShip Impact"}},{path:"compare",loadComponent:()=>import("./chunk-WCKHQIYN.js").then(e=>e.Compare),data:{nav:"compare",title:"Compare projects"}},{path:"tips",loadComponent:()=>import("./chunk-A5R3MJMO.js").then(e=>e.Tips),data:{nav:"tips",title:"Tips"}},{path:"memory",loadComponent:()=>import("./chunk-45QHGCB4.js").then(e=>e.Memory),data:{nav:"memory",title:"Memory"}},{path:"design",loadComponent:()=>import("./chunk-WAI2JMZP.js").then(e=>e.Design),data:{nav:"design",title:"Design system"}},{path:"settings",loadComponent:()=>import("./chunk-TPDB5GJN.js").then(e=>e.Settings),data:{nav:"settings",title:"Settings"}},{path:"**",redirectTo:"dashboard"}];var be={providers:[oe(),ge(_e)]};function xe(e,n){e&1&&(ee(),C(0,"rect",14)(1,"rect",15))}var q=class e{size=E(24);tile=E(!0);glow=E(!0);static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-logo-mark"]],inputs:{size:[1,"size"],tile:[1,"tile"],glow:[1,"glow"]},decls:16,vars:5,consts:[["viewBox","0 0 32 32","fill","none",2,"flex-shrink","0"],["id","ssTile","x1","0","y1","0","x2","32","y2","32","gradientUnits","userSpaceOnUse"],["stop-color","#12161E"],["offset","1","stop-color","#0B0D11"],["id","ssLead","x1","18","y1","11","x2","26","y2","21","gradientUnits","userSpaceOnUse"],["stop-color","#6FA0F6"],["offset","1","stop-color","#5B93F2"],["transform","translate(4.6 4.6) scale(0.715)"],["d","M5 16 H11 M11 9 L23 16 L11 23","stroke","rgba(150,165,200,0.5)","stroke-width","1.9","stroke-linecap","round","stroke-linejoin","round","fill","none"],["x1","11","y1","9","x2","11","y2","23","stroke","rgba(150,165,200,0.4)","stroke-width","1.9","stroke-linecap","round"],["cx","23","cy","16","r","3.6","fill","url(#ssLead)"],["cx","11","cy","9","r","2.9","fill","#A586F5"],["cx","11","cy","23","r","2.9","fill","#46C26B"],["cx","5","cy","16","r","2.1","fill","#29D2BE"],["width","32","height","32","rx","7.2","fill","url(#ssTile)"],["x","0.5","y","0.5","width","31","height","31","rx","6.7","fill","none","stroke","rgba(255,255,255,0.08)"]],template:function(t,i){t&1&&(ee(),p(0,"svg",0)(1,"defs")(2,"linearGradient",1),C(3,"stop",2)(4,"stop",3),u(),p(5,"linearGradient",4),C(6,"stop",5)(7,"stop",6),u()(),c(8,xe,2,0),p(9,"g",7),C(10,"path",8)(11,"line",9)(12,"circle",10)(13,"circle",11)(14,"circle",12)(15,"circle",13),u()()),t&2&&(se("filter",i.glow()?"drop-shadow(0 0 9px rgba(91,147,242,0.35))":"none"),M("width",i.size())("height",i.size()),o(8),m(i.tile()?8:-1))},styles:["[_nghost-%COMP%]{display:inline-flex;align-items:center;justify-content:center;line-height:0}"],changeDetection:0})};var Ce=e=>["/",e],ye=(e,n)=>n.group,Pe=(e,n)=>n.id;function ke(e,n){e&1&&(a(0,"div",3),s(1,"SpecShip "),a(2,"span",14),s(3,"Desktop"),r()())}function we(e,n){if(e&1&&(a(0,"div",15),s(1),r()),e&2){let t=g().$implicit;o(),h(t.group)}}function Se(e,n){if(e&1&&(a(0,"span",18),s(1),r()),e&2){let t=g(2).$implicit,i=g(2);M("data-kind",t.badgeKind),o(),h(i.badgeOf(t))}}function Me(e,n){if(e&1&&(a(0,"span",11),s(1),r(),c(2,Se,2,2,"span",18)),e&2){let t=g().$implicit,i=g(2);o(),h(t.label),o(),m(i.badgeOf(t)>0?2:-1)}}function Ee(e,n){if(e&1&&(a(0,"a",16),d(1,"span",8),a(2,"span",9),d(3,"app-icon",17),r(),c(4,Me,3,2),r()),e&2){let t=n.$implicit,i=g(2);v("routerLink",pe(5,Ce,t.id))("title",i.collapsed()?t.label:null),o(3),v("name",t.icon)("size",16),o(),m(i.collapsed()?-1:4)}}function Oe(e,n){if(e&1&&(a(0,"div",5),c(1,we,2,1,"div",15),T(2,Ee,5,7,"a",16,Pe),r()),e&2){let t=n.$implicit,i=g();o(),m(i.collapsed()?-1:1),o(),j(t.items)}}function Te(e,n){e&1&&(a(0,"span",11),s(1,"Design system"),r())}function je(e,n){e&1&&(a(0,"span",11),s(1,"Settings"),r())}var K=class e{collapsed=E(!1);api=f(H);projects=f(I);status=L(this.api,()=>`/api/status${this.projects.projectQuery()}`);tips=L(this.api,()=>"/api/claude/tips");improvements=L(this.api,()=>"/api/reflect?state=open");nav=[{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:()=>this.status.state().data?.drift??0,badgeKind:"warn"},{id:"improvements",label:"Improvements",icon:"sparkles",badge:()=>(this.improvements.state().data?.proposals??[]).filter(n=>n.severity==="high").length,badgeKind:"error"},{id:"workflows",label:"Workflows",icon:"workflow"},{id:"runs",label:"Runs",icon:"play"},{id:"chat",label:"Chat",icon:"chat"}]},{group:"Claude Code",items:[{id:"sessions",label:"Sessions",icon:"sessions"},{id:"heatmap",label:"Heatmap",icon:"heatmap"},{id:"costs",label:"Costs",icon:"dollar"},{id:"specship-impact",label:"SpecShip Impact",icon:"graph"},{id:"compare",label:"Compare projects",icon:"compare"},{id:"memory",label:"Memory",icon:"memory"},{id:"tips",label:"Tips",icon:"tips",badge:()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity!=="info").length,badgeKind:"error"}]}];badgeOf(n){return n.badge?n.badge():0}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-sidebar"]],inputs:{collapsed:[1,"collapsed"]},decls:18,vars:10,consts:[[1,"sidebar"],[1,"brand"],[3,"size"],[1,"brand-text"],[1,"scroll-y","nav-scroll"],[1,"nav-group"],[1,"pinned"],["routerLink","/design","routerLinkActive","active",1,"nav-item",3,"title"],[1,"indicator"],[1,"nav-icon"],["name","palette",3,"size"],[1,"nav-label"],["routerLink","/settings","routerLinkActive","active",1,"nav-item",3,"title"],["name","settings",3,"size"],[1,"muted"],[1,"eyebrow","group-label"],["routerLinkActive","active",1,"nav-item",3,"routerLink","title"],[3,"name","size"],[1,"badge"]],template:function(t,i){t&1&&(a(0,"nav",0)(1,"div",1),d(2,"app-logo-mark",2),c(3,ke,4,0,"div",3),r(),a(4,"div",4),T(5,Oe,4,1,"div",5,ye),r(),a(7,"div",6)(8,"a",7),d(9,"span",8),a(10,"span",9),d(11,"app-icon",10),r(),c(12,Te,2,0,"span",11),r(),a(13,"a",12),d(14,"span",8),a(15,"span",9),d(16,"app-icon",13),r(),c(17,je,2,0,"span",11),r()()()),t&2&&(w("collapsed",i.collapsed()),o(2),v("size",26),o(),m(i.collapsed()?-1:3),o(2),j(i.nav),o(3),v("title",i.collapsed()?"Design system":null),o(3),v("size",16),o(),m(i.collapsed()?-1:12),o(),v("title",i.collapsed()?"Settings":null),o(3),v("size",16),o(),m(i.collapsed()?-1:17))},dependencies:[me,ue,R,q],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.sidebar[_ngcontent-%COMP%]{width:var(--sidebar-w);flex-shrink:0;background:var(--bg-panel);border-right:1px solid var(--border-subtle);display:flex;flex-direction:column;transition:width .12s;overflow:hidden;font-family:var(--font-ui)}.sidebar.collapsed[_ngcontent-%COMP%]{width:var(--sidebar-w-collapsed)}.brand[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:15px 16px}.collapsed[_ngcontent-%COMP%] .brand[_ngcontent-%COMP%]{justify-content:center;padding:14px 0}.brand-text[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px;letter-spacing:-.01em}.brand-text[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted);font-weight:400}.nav-scroll[_ngcontent-%COMP%]{flex:1;padding:4px 8px}.nav-group[_ngcontent-%COMP%]{margin-bottom:10px}.group-label[_ngcontent-%COMP%]{padding:8px 8px 4px}.nav-item[_ngcontent-%COMP%]{position:relative;display:flex;align-items:center;gap:10px;height:32px;padding:0 10px;border-radius:7px;text-decoration:none;margin-bottom:1px;color:var(--text-secondary);font-weight:450;font-size:13px;transition:background .1s}.collapsed[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%]{padding:0;justify-content:center}.nav-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%]{background:var(--bg-active);color:var(--text-primary);font-weight:600}.nav-item.active[_ngcontent-%COMP%] .indicator[_ngcontent-%COMP%]{position:absolute;left:0;top:7px;bottom:7px;width:2.5px;border-radius:2px;background:var(--accent)}.nav-icon[_ngcontent-%COMP%]{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--text-secondary)}.nav-item[_ngcontent-%COMP%]:hover .nav-icon[_ngcontent-%COMP%]{color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%] .nav-icon[_ngcontent-%COMP%]{color:var(--accent)}.nav-label[_ngcontent-%COMP%]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.badge[_ngcontent-%COMP%]{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10px;font-weight:700;padding:1px 6px;min-width:18px;border-radius:999px;display:inline-flex;justify-content:center;color:var(--text-secondary);background:#ffffff0f}.badge[data-kind=error][_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.badge[data-kind=warn][_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pinned[_ngcontent-%COMP%]{padding:8px;border-top:1px solid var(--border-subtle)}'],changeDetection:0})};function De(e,n){if(e&1&&(p(0,"span",8),s(1),u(),C(2,"span",1),p(3,"span",9)(4,"span",10),s(5,"nodes"),u(),p(6,"span",4),s(7),u()(),p(8,"span",9)(9,"span",10),s(10,"edges"),u(),p(11,"span",4),s(12),u()(),C(13,"span",1),p(14,"span",9)(15,"span",10),s(16,"drift"),u(),p(17,"span",4),s(18),u()(),C(19,"span",11),p(20,"span",9)(21,"span",10),s(22,"indexed"),u(),p(23,"span",4),s(24),u()()),e&2){let t=g(),i=t.status.state().data;o(),h(i.projectPath),o(6),h(i.nodeCount.toLocaleString()),o(5),h(i.edgeCount.toLocaleString()),o(5),w("warn",i.drift>0)("success",i.drift===0),o(),h(i.drift),o(6),h(t.indexedLabel())}}function ze(e,n){e&1&&(p(0,"span",12),s(1,"loading status\u2026"),u(),C(2,"span",11))}function Ie(e,n){if(e&1&&(p(0,"span",12),s(1),u(),C(2,"span",11)),e&2){let t=g();o(),h(t.conn.online()?"no backend":"offline \u2014 no cached data")}}function Le(e,n){e&1&&(p(0,"span",5),s(1),u()),e&2&&(o(),F("\xB7 ",n))}function Re(e,n){e&1&&(p(0,"span",6),s(1,"\u26A0"),u()),e&2&&V("title",n)}var W=class e{api=f(H);projects=f(I);refreshSvc=f(ve);conn=f(fe);status=L(this.api,()=>`/api/status${this.projects.projectQuery()}`);offlineAge=D(()=>{let n=this.status.state().cachedAt??this.conn.lastOnlineAt();if(n===null)return null;let t=Date.now()-n;return t<1e4?"just now":t<6e4?`${Math.round(t/1e3)}s ago`:t<36e5?`${Math.round(t/6e4)}m ago`:t<864e5?`${Math.round(t/36e5)}h ago`:`${Math.round(t/864e5)}d ago`});indexedLabel=D(()=>{let n=this.status.state().data?.lastIndexed;if(!n)return"never";try{let t=new Date(n),i=Date.now()-t.getTime();return i<6e4?"just now":i<36e5?`${Math.round(i/6e4)}m ago`:i<864e5?`${Math.round(i/36e5)}h ago`:t.toLocaleDateString()}catch{return String(n)}});async refresh(){await this.refreshSvc.triggerGlobalRefresh()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-status-strip"]],decls:13,vars:14,consts:[[1,"status-strip"],[1,"divider"],[1,"seg","conn",3,"title"],[1,"conn-dot"],[1,"mono","val"],[1,"muted","conn-age"],[1,"refresh-error","mono",3,"title"],[1,"refresh",3,"click","disabled","title"],[1,"seg","mono"],[1,"seg"],[1,"lbl"],[1,"grow"],[1,"mono","muted"]],template:function(t,i){if(t&1&&(p(0,"div",0),c(1,De,25,9)(2,ze,3,0)(3,Ie,3,1),C(4,"span",1),p(5,"span",2),C(6,"span",3),p(7,"span",4),s(8),u(),c(9,Le,2,1,"span",5),u(),c(10,Re,2,1,"span",6),p(11,"button",7),A("click",function(){return i.refresh()}),s(12,"\u21BB"),u()()),t&2){let l,_;o(),m(i.status.state().data?1:i.status.state().loading?2:3),o(4),V("title",i.conn.online()?"Connected to the SpecShip server":"Server unreachable \u2014 showing the last cached data"),o(),w("live",i.conn.online())("off",!i.conn.online()),o(2),h(i.conn.online()?"Live":"Offline"),o(),m((l=!i.conn.online()&&i.offlineAge())?9:-1,l),o(),m((_=i.refreshSvc.error())?10:-1,_),o(),w("spinning",i.refreshSvc.loading()),V("disabled",i.refreshSvc.loading()||!i.conn.online())("title",i.conn.online()?i.refreshSvc.loading()?"Refreshing\u2026":"Refresh: sync index + re-ingest Claude Code transcripts. Updates Sessions, Heatmap, Costs, Memory, Drift, Graph.":"Offline \u2014 reconnect to refresh"),M("aria-label",i.conn.online()?i.refreshSvc.loading()?"Refreshing\u2026":"Refresh everything \u2014 sync index + ingest Claude Code transcripts":"Offline \u2014 reconnect to refresh")}},styles:["[_nghost-%COMP%]{display:contents}.status-strip[_ngcontent-%COMP%]{height:var(--status-h);flex-shrink:0;display:flex;align-items:center;gap:14px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel-2);font-size:11.5px;overflow:hidden;white-space:nowrap}.seg[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;flex-shrink:0}.lbl[_ngcontent-%COMP%]{color:var(--text-muted);font-size:11px}.val[_ngcontent-%COMP%]{color:var(--text-secondary);font-variant-numeric:tabular-nums}.val.warn[_ngcontent-%COMP%]{color:var(--warn)}.val.success[_ngcontent-%COMP%]{color:var(--success)}.divider[_ngcontent-%COMP%]{width:1px;height:12px;background:var(--border-subtle);flex-shrink:0}.grow[_ngcontent-%COMP%]{flex:1}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.refresh[_ngcontent-%COMP%]{background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:14px;padding:2px 6px;border-radius:4px;transition:background .12s,color .12s}.refresh[_ngcontent-%COMP%]:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}.refresh[_ngcontent-%COMP%]:disabled{cursor:progress;opacity:.8}.refresh[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.refresh.spinning[_ngcontent-%COMP%]{display:inline-block;animation:_ngcontent-%COMP%_spin .9s linear infinite;color:var(--accent)}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.refresh-error[_ngcontent-%COMP%]{color:var(--warn);font-size:12px;padding:0 2px;cursor:help}.conn[_ngcontent-%COMP%]{gap:5px}.conn-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.conn-dot.live[_ngcontent-%COMP%]{background:var(--success);box-shadow:0 0 6px var(--success)}.conn-dot.off[_ngcontent-%COMP%]{background:var(--warn);box-shadow:0 0 6px var(--warn)}.conn-age[_ngcontent-%COMP%]{font-size:11px}"],changeDetection:0})};var Ne=(e,n)=>n.slug;function Ae(e,n){e&1&&d(0,"span",8)}function Fe(e,n){e&1&&d(0,"span",9)}function Be(e,n){e&1&&d(0,"span",10)}function $e(e,n){if(e&1&&(a(0,"span",7),s(1),r(),c(2,Ae,1,0,"span",8)(3,Fe,1,0,"span",9)(4,Be,1,0,"span",10)),e&2){let t=n,i=g();o(),h(i.shortPath(t.path)),o(),m(t.exists?t.initialized?4:3:2)}}function Ve(e,n){e&1&&(a(0,"span",3),s(1,"Select project"),r())}function He(e,n){if(e&1){let t=k();a(0,"button",20),b("click",function(){y(t);let l=g(2);return P(l.clear())}),d(1,"app-icon",21),s(2," Clear "),r()}e&2&&(o(),v("size",11))}function Ge(e,n){e&1&&(a(0,"span",16),s(1,"\xB7 loading\u2026"),r())}function qe(e,n){if(e&1&&(a(0,"span",16),s(1),r()),e&2){let t=g(2);o(),F("\xB7 ",t.filtered().length," shown \xB7 live")}}function Ke(e,n){e&1&&(a(0,"div",18),s(1,"No projects match."),r())}function We(e,n){e&1&&(a(0,"span",25),s(1,"missing"),r())}function Ue(e,n){e&1&&(a(0,"span",26),s(1,"not init"),r())}function Qe(e,n){e&1&&(a(0,"span",27),s(1,"initialized"),r())}function Je(e,n){if(e&1&&(a(0,"span"),s(1),r()),e&2){let t=g().$implicit,i=g(2);o(),F("\xB7 ",i.formatRelative(t.lastModifiedMs))}}function Ye(e,n){e&1&&d(0,"app-icon",29),e&2&&v("size",13)}function Xe(e,n){if(e&1){let t=k();a(0,"button",22),b("click",function(){let l=y(t).$implicit,_=g(2);return P(_.pick(l.slug))}),a(1,"div",23)(2,"div",24)(3,"span",7),s(4),r(),c(5,We,2,0,"span",25)(6,Ue,2,0,"span",26)(7,Qe,2,0,"span",27),r(),a(8,"div",28)(9,"span"),s(10),r(),c(11,Je,2,1,"span"),r()(),c(12,Ye,1,1,"app-icon",29),r()}if(e&2){let t=n.$implicit,i=g(2);w("active",i.projects.activeSlug()===t.slug),o(4),h(i.shortPath(t.path)),o(),m(t.exists?t.initialized?7:6:5),o(5),le("",t.sessionCount," session",t.sessionCount===1?"":"s"),o(),m(t.lastModifiedMs>0?11:-1),o(),m(i.projects.activeSlug()===t.slug?12:-1)}}function Ze(e,n){if(e&1){let t=k();a(0,"div",6)(1,"div",11),d(2,"app-icon",12),a(3,"input",13),b("input",function(l){y(t);let _=g();return P(_.onQuery(l.target.value))}),r(),c(4,He,3,1,"button",14),r(),a(5,"div",15)(6,"span"),s(7),r(),c(8,Ge,2,0,"span",16)(9,qe,2,1,"span",16),r(),a(10,"div",17),c(11,Ke,2,0,"div",18),T(12,Xe,13,8,"button",19,Ne),r()()}if(e&2){let t=g();o(2),v("size",13),o(),v("value",t.query()),o(),m(t.projects.activeSlug()?4:-1),o(3),h(t.projects.claudeRoot()??"~/.claude/projects"),o(),m(t.projects.loading()?8:9),o(3),m(t.filtered().length===0&&!t.projects.loading()?11:-1),o(),j(t.filtered())}}var U=class e{host=f(ae);projects=f(I);open=S(!1);query=S("");filtered=D(()=>{let n=this.query().trim().toLowerCase(),t=this.projects.projects();return n?t.filter(i=>i.path.toLowerCase().includes(n)||i.slug.toLowerCase().includes(n)):t});badge=D(()=>this.projects.projects().length);toggle(){this.open.update(n=>!n)}pick(n){this.projects.setActive(n),this.open.set(!1),this.query.set("")}clear(){this.projects.setActive(null),this.open.set(!1)}onQuery(n){this.query.set(n)}onDocumentClick(n){if(!this.open())return;let t=n.target;t&&!this.host.nativeElement.contains(t)&&this.open.set(!1)}onEscape(){this.open()&&this.open.set(!1)}formatRelative(n){if(!n)return"";let t=Date.now()-n,i=Math.round(t/1e3);if(i<60)return`${i}s ago`;let l=Math.round(i/60);if(l<60)return`${l}m ago`;let _=Math.round(l/60);if(_<24)return`${_}h ago`;let ne=Math.round(_/24);return ne<30?`${ne}d ago`:new Date(n).toLocaleDateString()}shortPath(n){if(!n)return"";let t=this.detectHome();return t&&n===t?"~":t&&n.startsWith(t+"/")?"~/"+n.slice(t.length+1):n}detectHome(){let n=this.projects.claudeRoot();if(!n)return null;let t="/.claude/projects";return n.endsWith(t)?n.slice(0,-t.length):null}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-project-picker"]],hostBindings:function(t,i){t&1&&b("click",function(_){return i.onDocumentClick(_)},te)("keydown.escape",function(){return i.onEscape()},te)},decls:9,vars:9,consts:[[1,"wrap"],["type","button","aria-label","Switch project",1,"trigger",3,"click"],["name","folder",3,"size"],[1,"placeholder"],[1,"badge","mono"],[3,"name","size"],["role","dialog","aria-label","Pick a project",1,"popover"],[1,"path","mono"],["title","path no longer exists on disk",1,"status-dot","missing"],["title","not yet specship init'd",1,"status-dot","warn"],["title","initialized",1,"status-dot","ok"],[1,"popover-head","row","gap-8"],["name","search",3,"size"],["type","text","placeholder","Filter projects\u2026","autofocus","",1,"popover-input",3,"input","value"],["title","Clear selection",1,"btn","btn-ghost","btn-xs"],[1,"popover-meta","mono"],[1,"muted"],[1,"popover-list","scroll-y"],[1,"empty"],["type","button",1,"row-item",3,"active"],["title","Clear selection",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],["type","button",1,"row-item",3,"click"],[1,"col","gap-2","grow"],[1,"row","gap-6","path-line"],[1,"pill","missing"],[1,"pill","warn"],[1,"pill","ok"],[1,"meta","row","gap-8","mono","muted"],["name","check",3,"size"]],template:function(t,i){if(t&1&&(a(0,"div",0)(1,"button",1),b("click",function(){return i.toggle()}),d(2,"app-icon",2),c(3,$e,5,2)(4,Ve,2,0,"span",3),a(5,"span",4),s(6),r(),d(7,"app-icon",5),r(),c(8,Ze,14,6,"div",6),r()),t&2){let l;w("open",i.open()),o(),M("aria-expanded",i.open()),o(),v("size",13),o(),m((l=i.projects.active())?3:4,l),o(3),h(i.badge()),o(),v("name",i.open()?"chevronDown":"chevronRight")("size",11),o(),m(i.open()?8:-1)}},dependencies:[R],styles:["[_nghost-%COMP%]{display:inline-flex;min-width:0}.wrap[_ngcontent-%COMP%]{position:relative;min-width:0}.trigger[_ngcontent-%COMP%]{height:30px;padding:0 11px 0 10px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;color:var(--text-secondary);display:inline-flex;align-items:center;gap:8px;font-family:var(--font-ui);font-size:12.5px;cursor:pointer;max-width:360px;min-width:0;transition:background .1s,border-color .1s}.trigger[_ngcontent-%COMP%]:hover, .wrap.open[_ngcontent-%COMP%] .trigger[_ngcontent-%COMP%]{background:var(--bg-panel-2);border-color:var(--border-strong);color:var(--text-primary)}.trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.trigger[_ngcontent-%COMP%]:hover app-icon[_ngcontent-%COMP%]{color:var(--text-secondary)}.path[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.placeholder[_ngcontent-%COMP%]{color:var(--text-muted);font-style:italic}.status-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.status-dot.ok[_ngcontent-%COMP%]{background:var(--success)}.status-dot.warn[_ngcontent-%COMP%]{background:var(--warn)}.status-dot.missing[_ngcontent-%COMP%]{background:var(--error)}.badge[_ngcontent-%COMP%]{font-size:10px;padding:1px 6px;border-radius:999px;background:var(--bg-active);color:var(--text-muted);font-variant-numeric:tabular-nums;flex-shrink:0}.popover[_ngcontent-%COMP%]{position:absolute;top:calc(100% + 6px);left:0;z-index:30;width:420px;max-width:calc(100vw - 40px);background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:10px;box-shadow:var(--shadow-pop);display:flex;flex-direction:column;max-height:480px;animation:_ngcontent-%COMP%_pp-in .12s ease-out}@keyframes _ngcontent-%COMP%_pp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.popover-head[_ngcontent-%COMP%]{padding:10px 12px 8px;border-bottom:1px solid var(--border-subtle)}.popover-head[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.popover-input[_ngcontent-%COMP%]{flex:1;min-width:0;background:transparent;border:none;outline:none;font-family:var(--font-ui);font-size:13px;color:var(--text-primary)}.popover-input[_ngcontent-%COMP%]::placeholder{color:var(--text-muted)}.popover-meta[_ngcontent-%COMP%]{padding:6px 12px 8px;font-size:10.5px;color:var(--text-secondary);border-bottom:1px solid var(--border-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.popover-meta[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted)}.popover-list[_ngcontent-%COMP%]{flex:1;min-height:0;padding:4px}.row-item[_ngcontent-%COMP%]{width:100%;display:flex;align-items:center;gap:10px;padding:9px 10px;border:none;border-radius:7px;background:transparent;color:inherit;cursor:pointer;font-family:inherit;text-align:left;transition:background 80ms}.row-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.row-item.active[_ngcontent-%COMP%]{background:var(--accent-soft);color:var(--text-primary)}.row-item.active[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--accent)}.path-line[_ngcontent-%COMP%]{min-width:0}.path-line[_ngcontent-%COMP%] .path[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta[_ngcontent-%COMP%]{font-size:10.5px}.pill[_ngcontent-%COMP%]{font-size:10px;font-weight:600;padding:1px 7px;border-radius:999px;white-space:nowrap;flex-shrink:0}.pill.ok[_ngcontent-%COMP%]{color:var(--success);background:var(--success-soft)}.pill.warn[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pill.missing[_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.empty[_ngcontent-%COMP%]{text-align:center;color:var(--text-muted);font-size:12px;padding:18px 12px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1;min-width:0}.row[_ngcontent-%COMP%]{display:flex;align-items:center}.col[_ngcontent-%COMP%]{display:flex;flex-direction:column}.gap-2[_ngcontent-%COMP%]{gap:2px}.gap-6[_ngcontent-%COMP%]{gap:6px}.gap-8[_ngcontent-%COMP%]{gap:8px}.scroll-y[_ngcontent-%COMP%]{overflow-y:auto;overflow-x:hidden}"],changeDetection:0})};var Q=class e{deferred=null;canInstall=S(!1);constructor(){typeof window>"u"||window.matchMedia?.("(display-mode: standalone)").matches===!0||window.navigator.standalone===!0||(window.addEventListener("beforeinstallprompt",t=>{t.preventDefault(),this.deferred=t,this.canInstall.set(!0)}),window.addEventListener("appinstalled",()=>{this.deferred=null,this.canInstall.set(!1)}))}async install(){let n=this.deferred;if(n){this.deferred=null,this.canInstall.set(!1);try{await n.prompt(),await n.userChoice}catch{}}}static \u0275fac=function(t){return new(t||e)};static \u0275prov=$({token:e,factory:e.\u0275fac,providedIn:"root"})};function et(e,n){if(e&1){let t=k();a(0,"button",9),b("click",function(){y(t);let l=g();return P(l.onInstall())}),d(1,"app-icon",10),a(2,"span"),s(3,"Install"),r()()}e&2&&(o(),v("size",14))}var J=class e{toggleSidebar=B();openPalette=B();theme=f(G);effective=this.theme.effective;pwa=f(Q);onToggleTheme(){this.theme.toggle()}onMenuClick(){this.toggleSidebar.emit()}onPalette(){this.openPalette.emit()}onInstall(){this.pwa.install()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-top-bar"]],outputs:{toggleSidebar:"toggleSidebar",openPalette:"openPalette"},decls:14,vars:6,consts:[[1,"topbar"],["title","Toggle sidebar","aria-label","Toggle sidebar",1,"ghost","icon-btn",3,"click"],["name","menu",3,"size"],["aria-label","Open command palette",1,"palette-trigger",3,"click"],["name","search",3,"size"],[1,"grow"],["title","Install SpecShip as an app","aria-label","Install SpecShip as an app",1,"ghost",2,"display","inline-flex","align-items","center","gap","6px","padding","0 10px","height","30px","font-size","12px"],["aria-label","Toggle theme",1,"ghost","icon-btn",3,"click","title"],[3,"name","size"],["title","Install SpecShip as an app","aria-label","Install SpecShip as an app",1,"ghost",2,"display","inline-flex","align-items","center","gap","6px","padding","0 10px","height","30px","font-size","12px",3,"click"],["name","plus",3,"size"]],template:function(t,i){t&1&&(a(0,"div",0)(1,"button",1),b("click",function(){return i.onMenuClick()}),d(2,"app-icon",2),r(),d(3,"app-project-picker"),a(4,"button",3),b("click",function(){return i.onPalette()}),d(5,"app-icon",4),a(6,"span"),s(7,"Search or jump to\u2026"),r(),a(8,"kbd"),s(9,"\u2318K"),r()(),d(10,"span",5),c(11,et,4,1,"button",6),a(12,"button",7),b("click",function(){return i.onToggleTheme()}),d(13,"app-icon",8),r()()),t&2&&(o(2),v("size",16),o(3),v("size",13),o(6),m(i.pwa.canInstall()?11:-1),o(),v("title","Theme: "+i.effective()),o(),v("name",i.effective()==="dark"?"sun":"moon")("size",16))},dependencies:[R,U],styles:["[_nghost-%COMP%]{display:contents}.topbar[_ngcontent-%COMP%]{height:44px;flex-shrink:0;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-canvas)}.ghost[_ngcontent-%COMP%]{background:transparent;border:1px solid transparent;color:var(--text-secondary);cursor:pointer}.ghost[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.icon-btn[_ngcontent-%COMP%]{padding:6px 9px;border-radius:5px;font-size:16px}.palette-trigger[_ngcontent-%COMP%]{flex:1;max-width:380px;height:30px;padding:0 11px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;cursor:text;color:var(--text-muted);font-size:12.5px;text-align:left;display:flex;align-items:center;gap:8px}.palette-trigger[_ngcontent-%COMP%]:hover{border-color:var(--border-strong);color:var(--text-secondary)}.palette-trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted)}.palette-trigger[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{flex:1}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}.grow[_ngcontent-%COMP%]{flex:1}"],changeDetection:0})};var tt=(e,n)=>n.id;function nt(e,n){if(e&1){let t=k();p(0,"button",6),A("click",function(){let l=y(t).$implicit,_=g(2);return P(_.go(l.id))}),p(1,"span",7),s(2),u(),p(3,"span",8),s(4),u()()}if(e&2){let t=n.$implicit;o(2),h(t.label),o(2),h(t.sub)}}function it(e,n){if(e&1){let t=k();p(0,"div",1),A("click",function(l){y(t);let _=g();return P(_.onBackdrop(l))}),p(1,"div",2)(2,"div",3)(3,"span"),s(4,"Jump to\u2026"),u(),p(5,"kbd"),s(6,"esc"),u()(),p(7,"div",4),T(8,nt,5,2,"button",5,tt),u()()()}if(e&2){let t=g();o(8),j(t.items)}}var ot=[{id:"dashboard",label:"Dashboard",sub:"/dashboard"},{id:"graph",label:"Graph",sub:"/graph"},{id:"specs",label:"Specs",sub:"/specs"},{id:"drift",label:"Drift queue",sub:"/drift"},{id:"workflows",label:"Workflows",sub:"/workflows"},{id:"runs",label:"Runs",sub:"/runs"},{id:"chat",label:"Chat",sub:"/chat"},{id:"sessions",label:"Sessions",sub:"/sessions"},{id:"heatmap",label:"Heatmap",sub:"/heatmap"},{id:"costs",label:"Costs",sub:"/costs"},{id:"compare",label:"Compare projects",sub:"/compare"},{id:"tips",label:"Tips",sub:"/tips"},{id:"settings",label:"Settings",sub:"/settings"}],Y=class e{open=E(!1);close=B();router=f(z);items=ot;go(n){this.router.navigate(["/"+n]),this.close.emit()}onBackdrop(n){n.target===n.currentTarget&&this.close.emit()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-command-palette"]],inputs:{open:[1,"open"]},outputs:{close:"close"},decls:1,vars:1,consts:[[1,"backdrop"],[1,"backdrop",3,"click"],[1,"palette"],[1,"palette-header"],[1,"palette-list","scroll-y"],[1,"item"],[1,"item",3,"click"],[1,"label"],[1,"sub","mono"]],template:function(t,i){t&1&&c(0,it,10,0,"div",0),t&2&&m(i.open()?0:-1)},styles:["[_nghost-%COMP%]{display:contents}.backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:grid;place-items:start center;padding-top:12vh;z-index:100;animation:fadeIn .1s}.palette[_ngcontent-%COMP%]{width:560px;max-width:90vw;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-pop);overflow:hidden}.palette-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:12px 14px;border-bottom:1px solid var(--border-subtle);font-size:13px}.palette-list[_ngcontent-%COMP%]{max-height:380px;padding:6px}.item[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:7px;cursor:pointer;color:var(--text-primary);font-family:inherit;font-size:13px;text-align:left}.item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.label[_ngcontent-%COMP%]{flex:1}.sub[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted)}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}"],changeDetection:0})};var X=class e{es=null;notify=f(he);router=f(z);start(){if(!(this.es||typeof EventSource>"u")){try{this.es=new EventSource("/api/events")}catch{return}this.es.onmessage=n=>{let t;try{t=JSON.parse(n.data)}catch{return}!t||t.kind!=="approval"&&t.kind!=="runDone"&&t.kind!=="drift"&&t.kind!=="reflect"||this.notify.notify(t.kind,t.title,{body:t.detail,tag:`${t.project}:${t.kind}:${t.id}`,onClick:()=>this.routeFor(t)})}}}stop(){this.es?.close(),this.es=null}routeFor(n){let t={project:n.project};n.kind==="drift"?this.router.navigate(["/drift"],{queryParams:t}):n.kind==="reflect"?this.router.navigate(["/improvements"],{queryParams:t}):this.router.navigate(["/runs",n.id],{queryParams:t})}static \u0275fac=function(t){return new(t||e)};static \u0275prov=$({token:e,factory:e.\u0275fac,providedIn:"root"})};var Z=class e{_theme=f(G);_destroyRef=f(ie);_router=f(z);_events=f(X);constructor(){this._events.start()}sidebarCollapsed=S(typeof window<"u"&&window.innerWidth<1100);paletteOpen=S(!1);gChord={armed:!1,t:0};onGlobalKey(n){let t=n.metaKey||n.ctrlKey;if(t&&n.key.toLowerCase()==="k"){n.preventDefault(),this.paletteOpen.update(i=>!i);return}if(n.key==="Escape"){this.paletteOpen.set(!1);return}if(!t&&n.key.toLowerCase()==="g"&&!this.gChord.armed){let i=n.target;if(i&&/input|textarea/i.test(i.tagName))return;this.gChord.armed=!0,this.gChord.t=Date.now(),setTimeout(()=>{this.gChord.armed=!1},600);return}if(this.gChord.armed&&!t){let i=n.key.toLowerCase();i==="d"?this._router.navigate(["/dashboard"]):i==="g"?this._router.navigate(["/graph"]):i==="s"&&this._router.navigate(["/specs"]),this.gChord.armed=!1}}toggleSidebar(){this.sidebarCollapsed.update(n=>!n)}onOpenPalette(){this.paletteOpen.set(!0)}onClosePalette(){this.paletteOpen.set(!1)}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-root"]],hostBindings:function(t,i){t&1&&b("keydown",function(_){return i.onGlobalKey(_)},re)},decls:8,vars:2,consts:[[1,"shell"],[3,"collapsed"],[1,"main"],[3,"toggleSidebar","openPalette"],[1,"page-frame"],[3,"close","open"]],template:function(t,i){t&1&&(a(0,"div",0),d(1,"app-sidebar",1),a(2,"div",2),d(3,"app-status-strip"),a(4,"app-top-bar",3),b("toggleSidebar",function(){return i.toggleSidebar()})("openPalette",function(){return i.onOpenPalette()}),r(),a(5,"div",4),d(6,"router-outlet"),r()(),a(7,"app-command-palette",5),b("close",function(){return i.onClosePalette()}),r()()),t&2&&(o(),v("collapsed",i.sidebarCollapsed()),o(6),v("open",i.paletteOpen()))},dependencies:[ce,K,W,J,Y],styles:["[_nghost-%COMP%]{display:block;height:100%}.shell[_ngcontent-%COMP%]{display:flex;height:100vh;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base)}.main[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.page-frame[_ngcontent-%COMP%]{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--bg-canvas)}"],changeDetection:0})};de(Z,be).catch(e=>console.error(e));typeof navigator<"u"&&"serviceWorker"in navigator&&window.addEventListener("load",()=>{navigator.serviceWorker.register("sw.js").catch(e=>{console.warn("[specship] offline service worker registration failed",e)})});