@selvakumaresra/specship 0.7.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 (143) hide show
  1. package/commands/ss-domain.md +98 -0
  2. package/commands/ss-triage.md +177 -0
  3. package/dist/bin/specship.js +308 -0
  4. package/dist/bin/specship.js.map +1 -1
  5. package/dist/db/migrations.d.ts +1 -1
  6. package/dist/db/migrations.d.ts.map +1 -1
  7. package/dist/db/migrations.js +28 -1
  8. package/dist/db/migrations.js.map +1 -1
  9. package/dist/db/schema.sql +26 -2
  10. package/dist/db/spec-queries.d.ts +29 -0
  11. package/dist/db/spec-queries.d.ts.map +1 -1
  12. package/dist/db/spec-queries.js +63 -0
  13. package/dist/db/spec-queries.js.map +1 -1
  14. package/dist/enforce/enforce.d.ts +70 -0
  15. package/dist/enforce/enforce.d.ts.map +1 -0
  16. package/dist/enforce/enforce.js +125 -0
  17. package/dist/enforce/enforce.js.map +1 -0
  18. package/dist/extraction/specs/markdown-spec-extractor.d.ts +21 -0
  19. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
  20. package/dist/extraction/specs/markdown-spec-extractor.js +144 -0
  21. package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
  22. package/dist/fitness/fitness.d.ts +75 -0
  23. package/dist/fitness/fitness.d.ts.map +1 -0
  24. package/dist/fitness/fitness.js +204 -0
  25. package/dist/fitness/fitness.js.map +1 -0
  26. package/dist/graph/maintainability.d.ts +101 -0
  27. package/dist/graph/maintainability.d.ts.map +1 -0
  28. package/dist/graph/maintainability.js +278 -0
  29. package/dist/graph/maintainability.js.map +1 -0
  30. package/dist/index.d.ts +65 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +149 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/installer/instructions-template.d.ts +5 -4
  35. package/dist/installer/instructions-template.d.ts.map +1 -1
  36. package/dist/installer/instructions-template.js +10 -4
  37. package/dist/installer/instructions-template.js.map +1 -1
  38. package/dist/installer/targets/claude.d.ts.map +1 -1
  39. package/dist/installer/targets/claude.js +4 -0
  40. package/dist/installer/targets/claude.js.map +1 -1
  41. package/dist/installer/targets/shared.d.ts.map +1 -1
  42. package/dist/installer/targets/shared.js +4 -0
  43. package/dist/installer/targets/shared.js.map +1 -1
  44. package/dist/mcp/fitness-tool.d.ts +12 -0
  45. package/dist/mcp/fitness-tool.d.ts.map +1 -0
  46. package/dist/mcp/fitness-tool.js +46 -0
  47. package/dist/mcp/fitness-tool.js.map +1 -0
  48. package/dist/mcp/maintainability-tool.d.ts +13 -0
  49. package/dist/mcp/maintainability-tool.d.ts.map +1 -0
  50. package/dist/mcp/maintainability-tool.js +64 -0
  51. package/dist/mcp/maintainability-tool.js.map +1 -0
  52. package/dist/mcp/server-instructions.d.ts +1 -1
  53. package/dist/mcp/server-instructions.d.ts.map +1 -1
  54. package/dist/mcp/server-instructions.js +3 -2
  55. package/dist/mcp/server-instructions.js.map +1 -1
  56. package/dist/mcp/spec-tools.d.ts.map +1 -1
  57. package/dist/mcp/spec-tools.js +115 -1
  58. package/dist/mcp/spec-tools.js.map +1 -1
  59. package/dist/mcp/tools.d.ts +13 -0
  60. package/dist/mcp/tools.d.ts.map +1 -1
  61. package/dist/mcp/tools.js +75 -0
  62. package/dist/mcp/tools.js.map +1 -1
  63. package/dist/reflect/apply.d.ts +31 -0
  64. package/dist/reflect/apply.d.ts.map +1 -0
  65. package/dist/reflect/apply.js +286 -0
  66. package/dist/reflect/apply.js.map +1 -0
  67. package/dist/reflect/hash.d.ts +20 -0
  68. package/dist/reflect/hash.d.ts.map +1 -0
  69. package/dist/reflect/hash.js +36 -0
  70. package/dist/reflect/hash.js.map +1 -0
  71. package/dist/reflect/index.d.ts +16 -0
  72. package/dist/reflect/index.d.ts.map +1 -0
  73. package/dist/reflect/index.js +43 -0
  74. package/dist/reflect/index.js.map +1 -0
  75. package/dist/reflect/miner.d.ts +21 -0
  76. package/dist/reflect/miner.d.ts.map +1 -0
  77. package/dist/reflect/miner.js +463 -0
  78. package/dist/reflect/miner.js.map +1 -0
  79. package/dist/reflect/store.d.ts +31 -0
  80. package/dist/reflect/store.d.ts.map +1 -0
  81. package/dist/reflect/store.js +101 -0
  82. package/dist/reflect/store.js.map +1 -0
  83. package/dist/reflect/sweep.d.ts +26 -0
  84. package/dist/reflect/sweep.d.ts.map +1 -0
  85. package/dist/reflect/sweep.js +42 -0
  86. package/dist/reflect/sweep.js.map +1 -0
  87. package/dist/reflect/targets.d.ts +52 -0
  88. package/dist/reflect/targets.d.ts.map +1 -0
  89. package/dist/reflect/targets.js +192 -0
  90. package/dist/reflect/targets.js.map +1 -0
  91. package/dist/reflect/types.d.ts +96 -0
  92. package/dist/reflect/types.d.ts.map +1 -0
  93. package/dist/reflect/types.js +13 -0
  94. package/dist/reflect/types.js.map +1 -0
  95. package/dist/resolution/domain-gap-seed.d.ts +60 -0
  96. package/dist/resolution/domain-gap-seed.d.ts.map +1 -0
  97. package/dist/resolution/domain-gap-seed.js +87 -0
  98. package/dist/resolution/domain-gap-seed.js.map +1 -0
  99. package/dist/resolution/spec-link-resolver.d.ts +46 -1
  100. package/dist/resolution/spec-link-resolver.d.ts.map +1 -1
  101. package/dist/resolution/spec-link-resolver.js +78 -0
  102. package/dist/resolution/spec-link-resolver.js.map +1 -1
  103. package/dist/server/routes/domain.js +0 -0
  104. package/dist/server/routes/events.js +20 -0
  105. package/dist/server/routes/maintainability.js +18 -0
  106. package/dist/server/routes/reflect.js +93 -0
  107. package/dist/server/server.js +6 -0
  108. package/dist/types.d.ts +4 -2
  109. package/dist/types.d.ts.map +1 -1
  110. package/dist/types.js +6 -0
  111. package/dist/types.js.map +1 -1
  112. package/dist/web/chunk-EZZBWC7Z.js +1 -0
  113. package/dist/web/chunk-ITHLF4GI.js +1 -0
  114. package/dist/web/{chunk-UBOZGQNK.js → chunk-IZQXYQNQ.js} +1 -1
  115. package/dist/web/chunk-JBO7ZIPO.js +1 -0
  116. package/dist/web/chunk-JQXCRIK2.js +1 -0
  117. package/dist/web/{chunk-ASZ77FMZ.js → chunk-JT2YIHPL.js} +1 -1
  118. package/dist/web/{chunk-WLIMNDS3.js → chunk-ONKHTXHJ.js} +1 -1
  119. package/dist/web/{chunk-FHZHD2ZG.js → chunk-P5JX67LT.js} +1 -1
  120. package/dist/web/chunk-PDTQX2UL.js +6 -0
  121. package/dist/web/chunk-TPDB5GJN.js +1 -0
  122. package/dist/web/{chunk-RASJHUXS.js → chunk-XWDR6MPC.js} +1 -1
  123. package/dist/web/chunk-Y6WWDS4R.js +1 -0
  124. package/dist/web/chunk-Z5L3T5EO.js +1 -0
  125. package/dist/web/{chunk-D5OCNEJA.js → chunk-ZG7H3XPL.js} +1 -1
  126. package/dist/web/index.html +1 -1
  127. package/dist/web/main-GYPY5V5H.js +1 -0
  128. package/dist/workflows/executor.d.ts.map +1 -1
  129. package/dist/workflows/executor.js +3 -0
  130. package/dist/workflows/executor.js.map +1 -1
  131. package/dist/workflows/runners/prompt.d.ts +31 -8
  132. package/dist/workflows/runners/prompt.d.ts.map +1 -1
  133. package/dist/workflows/runners/prompt.js +117 -23
  134. package/dist/workflows/runners/prompt.js.map +1 -1
  135. package/dist/workflows/runners/types.d.ts +7 -1
  136. package/dist/workflows/runners/types.d.ts.map +1 -1
  137. package/package.json +1 -1
  138. package/dist/web/chunk-HGBF7AY5.js +0 -1
  139. package/dist/web/chunk-JQ534IB6.js +0 -6
  140. package/dist/web/chunk-MVOMVPYB.js +0 -1
  141. package/dist/web/chunk-NZEZCT65.js +0 -1
  142. package/dist/web/chunk-WQWYTRFN.js +0 -1
  143. package/dist/web/main-LHCYPOXF.js +0 -1
@@ -1 +1 @@
1
- import{a as W}from"./chunk-X2HTISHL.js";import{a as Q}from"./chunk-UYC52MBC.js";import{a as U}from"./chunk-SUZYBYDW.js";import{b as Y,c as G}from"./chunk-GR72OOCN.js";import{d as B}from"./chunk-SHPTC4RL.js";import{a as H}from"./chunk-7RNS77UP.js";import{a as $}from"./chunk-E44X4RH2.js";import{Aa as m,Ea as T,Fa as O,I as c,Ia as S,Ka as C,R,Ta as D,Ua as I,Va as s,W as f,Wa as g,X as E,Xa as h,Za as z,bb as u,cb as F,ea as a,eb as j,gb as L,ib as N,ka as P,lb as w,qa as M,ra as v,sa as x,ua as k,va as y,vb as A,wa as b,xa as d,ya as r,za as o,zb as J}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var K=()=>({value:"time",label:"Latest"}),V=()=>({value:"cost",label:"Cost"}),X=()=>({value:"prompts",label:"Prompts"}),Z=(i,e,t)=>[i,e,t],ee=()=>[0,1,2,3,4],te=i=>["/sessions",i],ne=(i,e)=>e.fullId;function ie(i,e){i&1&&(r(0,"span",10),s(1,"\u26A0 refresh failed"),o()),i&2&&d("title",e)}function re(i,e){i&1&&(r(0,"div",20),m(1,"div",21),o())}function oe(i,e){i&1&&y(0,re,2,0,"div",20,k),i&2&&b(u(0,ee))}function se(i,e){i&1&&(r(0,"div",19),s(1," No sessions in this range. Either nothing's been logged yet, or the JSONL ingest watcher hasn't caught up \u2014 click Refresh. "),o())}function ae(i,e){if(i&1&&(r(0,"a",22)(1,"span",23),s(2),o(),r(3,"span",17)(4,"app-pill"),s(5),o()(),r(6,"span",24),s(7),o(),r(8,"span",25),s(9),o(),r(10,"span",25),s(11),L(12,"number"),o(),r(13,"span",26),s(14),o()()),i&2){let t=e.$implicit,n=C(2);d("routerLink",F(15,te,t.fullId)),M("aria-label","Open session "+t.id),a(2),g(t.id),a(3),g(t.project),a(2),z(" ",t.started," \u2013 ",t.ended," \xB7 ",t.model," "),a(2),g(t.prompts),a(),D("color",n.cacheColor(t.cache)),a(),h(" ",N(12,12,t.cache*100,"1.0-0"),"% "),a(3),h(" $",t.cost.toFixed(2)," ")}}function le(i,e){if(i&1&&y(0,ae,15,17,"a",22,ne),i&2){let t=C();b(t.sorted())}}var de=1e4,q=class i{api=c($);projects=c(H);refresh=c(Y);destroyRef=c(R);range=f("all");sort=f("time");ranges=["today","week","month","all"];localRefreshing=f(!1);resource=G(this.api,()=>`/api/claude/sessions?range=${this.range()}&limit=200${this.projects.projectQuery("&")}`);rows=w(()=>(this.resource.state().data?.sessions??[]).map(t=>this.adapt(t)));sorted=w(()=>{let e=this.sort();return[...this.rows()].sort((t,n)=>e==="cost"?n.cost-t.cost:e==="prompts"?n.prompts-t.prompts:n.startedAt-t.startedAt)});constructor(){let e=null,t=()=>{e===null&&(e=setInterval(()=>{typeof document<"u"&&document.visibilityState==="visible"&&this.resource.refetch()},de))},n=()=>{e!==null&&(clearInterval(e),e=null)},l=()=>{typeof document>"u"||document.visibilityState==="visible"&&this.resource.refetch()};t(),typeof document<"u"&&document.addEventListener("visibilitychange",l),this.destroyRef.onDestroy(()=>{n(),typeof document<"u"&&document.removeEventListener("visibilitychange",l)}),E(()=>{!this.resource.state().loading&&this.localRefreshing()&&this.localRefreshing.set(!1)})}async forceRefresh(){this.localRefreshing.set(!0),await this.refresh.triggerGlobalRefresh()}adapt(e){let t=(e.total_input_tokens||0)+(e.total_cache_creation_tokens||0)+(e.total_cache_read_tokens||0);return{id:(e.id||"").slice(0,8),fullId:e.id,project:(e.project_path||"").split("/").filter(Boolean).pop()||"?",startedAt:e.started_at||0,started:this.fmtTime(e.started_at),ended:this.fmtTime(e.ended_at).split(" ").pop()||"",prompts:e.prompt_count||0,cost:e.total_cost_usd||0,cache:t>0?(e.total_cache_read_tokens||0)/t:0,model:e.last_model||"unknown"}}fmtTime(e){if(!e)return"";try{let t=new Date(e),n=new Date;n.setHours(0,0,0,0);let l=864e5,p=n.getTime()-new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime(),_=t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});return p===0?"Today "+_:p===l?"Yest "+_:t.toLocaleDateString([],{month:"short",day:"numeric"})+" "+_}catch{return String(e)}}setSort(e){this.sort.set(e)}setRange(e){this.range.set(e)}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}static \u0275fac=function(t){return new(t||i)};static \u0275cmp=P({type:i,selectors:[["app-sessions"]],decls:35,vars:18,consts:[[1,"page"],[2,"padding","16px 18px 12px"],["icon","sessions","title","Sessions",3,"sub"],["actions",""],["type","button","title","Force refresh: sync the index + re-ingest Claude Code transcripts","aria-label","Refresh sessions",1,"btn","btn-secondary","btn-sm","refresh-btn",3,"click","disabled"],["name","refresh",3,"size"],[1,"filter-bar",2,"padding","0 18px 12px"],["name","filter",2,"color","var(--text-muted)",3,"size"],[1,"input",2,"font-size","12px","padding","4px 8px"],[1,"grow"],[2,"color","var(--warn)","font-size","11.5px","cursor","help",3,"title"],[1,"muted",2,"font-size","11.5px"],["size","sm",3,"change","value","options"],[1,"scroll-y",2,"flex","1","padding","0 18px 18px"],[1,"card",2,"overflow","hidden"],[1,"row",2,"padding","8px 14px","font-size","10.5px","color","var(--text-muted)","text-transform","uppercase","letter-spacing","0.05em","font-weight","600","border-bottom","1px solid var(--border-subtle)"],[2,"width","90px"],[2,"width","110px"],[2,"width","70px","text-align","right"],[2,"padding","28px 18px","text-align","center","color","var(--text-secondary)","font-size","12.5px","line-height","1.5"],[1,"row",2,"padding","10px 14px","border-top","1px solid var(--border-subtle)"],[1,"skel",2,"flex","1","height","18px"],[1,"row","session-row",2,"padding","11px 14px","border-top","1px solid var(--border-subtle)","display","flex","align-items","center","gap","0","text-decoration","none","color","inherit","cursor","pointer",3,"routerLink"],[1,"mono",2,"width","90px","font-size","12px"],[1,"mono","muted","grow",2,"font-size","11.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"mono","tabular",2,"width","70px","text-align","right","font-size","12px"],[1,"mono","tabular",2,"width","70px","text-align","right","font-size","12.5px","font-weight","600"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"div",1)(2,"app-page-head",2),T(3,3),r(4,"button",4),S("click",function(){return n.forceRefresh()}),m(5,"app-icon",5),s(6),o(),O(),o()(),r(7,"div",6),m(8,"app-icon",7),r(9,"select",8)(10,"option"),s(11,"All models"),o()(),m(12,"div",9),v(13,ie,2,1,"span",10),r(14,"span",11),s(15,"sort"),o(),r(16,"app-segmented",12),S("change",function(p){return n.setSort(p)}),o()(),r(17,"div",13)(18,"div",14)(19,"div",15)(20,"span",16),s(21,"Session"),o(),r(22,"span",17),s(23,"Project"),o(),r(24,"span",9),s(25,"Window"),o(),r(26,"span",18),s(27,"Prompts"),o(),r(28,"span",18),s(29,"Cache"),o(),r(30,"span",18),s(31,"Cost"),o()(),v(32,oe,2,1)(33,se,2,0,"div",19)(34,le,2,0),o()()()),t&2){let l;a(2),d("sub",n.resource.state().loading?"loading\u2026":n.sorted().length+" sessions \xB7 across all projects"),a(2),I("spinning",n.localRefreshing()||n.refresh.loading()),d("disabled",n.refresh.loading()),a(),d("size",13),a(),h(" ",n.localRefreshing()||n.refresh.loading()?"Refreshing\u2026":"Refresh"," "),a(2),d("size",13),a(5),x((l=n.refresh.error())?13:-1,l),a(3),d("value",n.sort())("options",j(14,Z,u(11,K),u(12,V),u(13,X))),a(16),x(n.resource.state().loading&&n.sorted().length===0?32:n.sorted().length===0?33:34)}},dependencies:[B,J,Q,U,W,A],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;min-height:0}.filter-bar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.row[_ngcontent-%COMP%]{display:flex;align-items:center}.session-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.session-row[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}.refresh-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px}.refresh-btn.spinning[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin .9s linear infinite;color:var(--accent)}.refresh-btn[_ngcontent-%COMP%]:disabled{cursor:progress;opacity:.8}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}"],changeDetection:0})};export{q as Sessions};
1
+ import{a as W}from"./chunk-X2HTISHL.js";import{a as Q}from"./chunk-UYC52MBC.js";import{a as U}from"./chunk-SUZYBYDW.js";import{d as B}from"./chunk-SHPTC4RL.js";import{b as Y,c as G}from"./chunk-GR72OOCN.js";import{a as H}from"./chunk-7RNS77UP.js";import{a as $}from"./chunk-E44X4RH2.js";import{Aa as m,Ea as T,Fa as O,I as c,Ia as S,Ka as C,R,Ta as D,Ua as I,Va as s,W as f,Wa as g,X as E,Xa as h,Za as z,bb as u,cb as F,ea as a,eb as j,gb as L,ib as N,ka as P,lb as w,qa as M,ra as v,sa as x,ua as k,va as y,vb as A,wa as b,xa as d,ya as r,za as o,zb as J}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var K=()=>({value:"time",label:"Latest"}),V=()=>({value:"cost",label:"Cost"}),X=()=>({value:"prompts",label:"Prompts"}),Z=(i,e,t)=>[i,e,t],ee=()=>[0,1,2,3,4],te=i=>["/sessions",i],ne=(i,e)=>e.fullId;function ie(i,e){i&1&&(r(0,"span",10),s(1,"\u26A0 refresh failed"),o()),i&2&&d("title",e)}function re(i,e){i&1&&(r(0,"div",20),m(1,"div",21),o())}function oe(i,e){i&1&&y(0,re,2,0,"div",20,k),i&2&&b(u(0,ee))}function se(i,e){i&1&&(r(0,"div",19),s(1," No sessions in this range. Either nothing's been logged yet, or the JSONL ingest watcher hasn't caught up \u2014 click Refresh. "),o())}function ae(i,e){if(i&1&&(r(0,"a",22)(1,"span",23),s(2),o(),r(3,"span",17)(4,"app-pill"),s(5),o()(),r(6,"span",24),s(7),o(),r(8,"span",25),s(9),o(),r(10,"span",25),s(11),L(12,"number"),o(),r(13,"span",26),s(14),o()()),i&2){let t=e.$implicit,n=C(2);d("routerLink",F(15,te,t.fullId)),M("aria-label","Open session "+t.id),a(2),g(t.id),a(3),g(t.project),a(2),z(" ",t.started," \u2013 ",t.ended," \xB7 ",t.model," "),a(2),g(t.prompts),a(),D("color",n.cacheColor(t.cache)),a(),h(" ",N(12,12,t.cache*100,"1.0-0"),"% "),a(3),h(" $",t.cost.toFixed(2)," ")}}function le(i,e){if(i&1&&y(0,ae,15,17,"a",22,ne),i&2){let t=C();b(t.sorted())}}var de=1e4,q=class i{api=c($);projects=c(H);refresh=c(Y);destroyRef=c(R);range=f("all");sort=f("time");ranges=["today","week","month","all"];localRefreshing=f(!1);resource=G(this.api,()=>`/api/claude/sessions?range=${this.range()}&limit=200${this.projects.projectQuery("&")}`);rows=w(()=>(this.resource.state().data?.sessions??[]).map(t=>this.adapt(t)));sorted=w(()=>{let e=this.sort();return[...this.rows()].sort((t,n)=>e==="cost"?n.cost-t.cost:e==="prompts"?n.prompts-t.prompts:n.startedAt-t.startedAt)});constructor(){let e=null,t=()=>{e===null&&(e=setInterval(()=>{typeof document<"u"&&document.visibilityState==="visible"&&this.resource.refetch()},de))},n=()=>{e!==null&&(clearInterval(e),e=null)},l=()=>{typeof document>"u"||document.visibilityState==="visible"&&this.resource.refetch()};t(),typeof document<"u"&&document.addEventListener("visibilitychange",l),this.destroyRef.onDestroy(()=>{n(),typeof document<"u"&&document.removeEventListener("visibilitychange",l)}),E(()=>{!this.resource.state().loading&&this.localRefreshing()&&this.localRefreshing.set(!1)})}async forceRefresh(){this.localRefreshing.set(!0),await this.refresh.triggerGlobalRefresh()}adapt(e){let t=(e.total_input_tokens||0)+(e.total_cache_creation_tokens||0)+(e.total_cache_read_tokens||0);return{id:(e.id||"").slice(0,8),fullId:e.id,project:(e.project_path||"").split("/").filter(Boolean).pop()||"?",startedAt:e.started_at||0,started:this.fmtTime(e.started_at),ended:this.fmtTime(e.ended_at).split(" ").pop()||"",prompts:e.prompt_count||0,cost:e.total_cost_usd||0,cache:t>0?(e.total_cache_read_tokens||0)/t:0,model:e.last_model||"unknown"}}fmtTime(e){if(!e)return"";try{let t=new Date(e),n=new Date;n.setHours(0,0,0,0);let l=864e5,p=n.getTime()-new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime(),_=t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});return p===0?"Today "+_:p===l?"Yest "+_:t.toLocaleDateString([],{month:"short",day:"numeric"})+" "+_}catch{return String(e)}}setSort(e){this.sort.set(e)}setRange(e){this.range.set(e)}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}static \u0275fac=function(t){return new(t||i)};static \u0275cmp=P({type:i,selectors:[["app-sessions"]],decls:35,vars:18,consts:[[1,"page"],[2,"padding","16px 18px 12px"],["icon","sessions","title","Sessions",3,"sub"],["actions",""],["type","button","title","Force refresh: sync the index + re-ingest Claude Code transcripts","aria-label","Refresh sessions",1,"btn","btn-secondary","btn-sm","refresh-btn",3,"click","disabled"],["name","refresh",3,"size"],[1,"filter-bar",2,"padding","0 18px 12px"],["name","filter",2,"color","var(--text-muted)",3,"size"],[1,"input",2,"font-size","12px","padding","4px 8px"],[1,"grow"],[2,"color","var(--warn)","font-size","11.5px","cursor","help",3,"title"],[1,"muted",2,"font-size","11.5px"],["size","sm",3,"change","value","options"],[1,"scroll-y",2,"flex","1","padding","0 18px 18px"],[1,"card",2,"overflow","hidden"],[1,"row",2,"padding","8px 14px","font-size","10.5px","color","var(--text-muted)","text-transform","uppercase","letter-spacing","0.05em","font-weight","600","border-bottom","1px solid var(--border-subtle)"],[2,"width","90px"],[2,"width","110px"],[2,"width","70px","text-align","right"],[2,"padding","28px 18px","text-align","center","color","var(--text-secondary)","font-size","12.5px","line-height","1.5"],[1,"row",2,"padding","10px 14px","border-top","1px solid var(--border-subtle)"],[1,"skel",2,"flex","1","height","18px"],[1,"row","session-row",2,"padding","11px 14px","border-top","1px solid var(--border-subtle)","display","flex","align-items","center","gap","0","text-decoration","none","color","inherit","cursor","pointer",3,"routerLink"],[1,"mono",2,"width","90px","font-size","12px"],[1,"mono","muted","grow",2,"font-size","11.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"mono","tabular",2,"width","70px","text-align","right","font-size","12px"],[1,"mono","tabular",2,"width","70px","text-align","right","font-size","12.5px","font-weight","600"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"div",1)(2,"app-page-head",2),T(3,3),r(4,"button",4),S("click",function(){return n.forceRefresh()}),m(5,"app-icon",5),s(6),o(),O(),o()(),r(7,"div",6),m(8,"app-icon",7),r(9,"select",8)(10,"option"),s(11,"All models"),o()(),m(12,"div",9),v(13,ie,2,1,"span",10),r(14,"span",11),s(15,"sort"),o(),r(16,"app-segmented",12),S("change",function(p){return n.setSort(p)}),o()(),r(17,"div",13)(18,"div",14)(19,"div",15)(20,"span",16),s(21,"Session"),o(),r(22,"span",17),s(23,"Project"),o(),r(24,"span",9),s(25,"Window"),o(),r(26,"span",18),s(27,"Prompts"),o(),r(28,"span",18),s(29,"Cache"),o(),r(30,"span",18),s(31,"Cost"),o()(),v(32,oe,2,1)(33,se,2,0,"div",19)(34,le,2,0),o()()()),t&2){let l;a(2),d("sub",n.resource.state().loading?"loading\u2026":n.sorted().length+" sessions \xB7 across all projects"),a(2),I("spinning",n.localRefreshing()||n.refresh.loading()),d("disabled",n.refresh.loading()),a(),d("size",13),a(),h(" ",n.localRefreshing()||n.refresh.loading()?"Refreshing\u2026":"Refresh"," "),a(2),d("size",13),a(5),x((l=n.refresh.error())?13:-1,l),a(3),d("value",n.sort())("options",j(14,Z,u(11,K),u(12,V),u(13,X))),a(16),x(n.resource.state().loading&&n.sorted().length===0?32:n.sorted().length===0?33:34)}},dependencies:[B,J,Q,U,W,A],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;min-height:0}.filter-bar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.row[_ngcontent-%COMP%]{display:flex;align-items:center}.session-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.session-row[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}.refresh-btn[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px}.refresh-btn.spinning[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_spin .9s linear infinite;color:var(--accent)}.refresh-btn[_ngcontent-%COMP%]:disabled{cursor:progress;opacity:.8}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}"],changeDetection:0})};export{q as Sessions};
@@ -1 +1 @@
1
- import{a as oe}from"./chunk-R5W2MDZN.js";import{a as ie}from"./chunk-WDU3WICG.js";import{b as ae}from"./chunk-HZA6NEAB.js";import{a as ne}from"./chunk-2GBEK2GM.js";import{a as te}from"./chunk-SUZYBYDW.js";import{c as K}from"./chunk-GR72OOCN.js";import{c as J}from"./chunk-SHPTC4RL.js";import{a as Z}from"./chunk-7RNS77UP.js";import{a as Y}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as y,I as N,Ia as b,Ka as c,M as h,N as v,O as f,P as C,Ta as I,Ua as R,Va as l,W as P,Wa as m,Xa as z,Za as W,bb as X,ea as o,ka as q,lb as w,qa as T,ra as g,sa as u,ua as G,va as k,wa as S,xa as x,ya as i,za as a,zb as ee}from"./chunk-PDN6QYGJ.js";import{a as A,b as U}from"./chunk-Q7L6LLAK.js";var de=()=>[1,2,3,4],pe=(t,n)=>n.node.id,L=(t,n)=>n.id;function se(t,n){t&1&&p(0,"app-pick-project-empty",0)}function ce(t,n){if(t&1){let e=y();i(0,"button",19),b("click",function(){let d=h(e).$implicit,s=c(2);return v(s.toggleFilter(d))}),p(1,"span",20),l(2),i(3,"span",21),l(4),a()()}if(t&2){let e=n.$implicit,r=c(2);I("--chip-color",r.chipColor(e)),R("is-active",r.isFilterActive(e)),o(),T("data-kind",e),o(),z(" ",r.kindLabel(e)," "),o(2),m(r.countFor(e))}}function me(t,n){t&1&&p(0,"span",12)}function ge(t,n){if(t&1){let e=y();i(0,"button",23),b("click",function(){let d=h(e).$implicit,s=c(3);return v(s.pickResult(d.node))}),p(1,"span",24),i(2,"span",25),l(3),a(),i(4,"span",26),l(5),a(),i(6,"span",27),l(7),a()()}if(t&2){let e=n.$implicit,r=c(3);o(),R("is-spec",e.node.kind==="spec")("is-route",e.node.kind==="route")("is-test",e.node.kind==="test"),o(2),m(e.node.name),o(2),m(e.node.kind),o(2),m(r.shortPath(e.node.filePath))}}function ue(t,n){if(t&1&&(i(0,"div",13),k(1,ge,8,9,"button",22,pe),a()),t&2){let e=c(2);o(),S(e.searchResults.state().data.results)}}function _e(t,n){if(t&1&&(i(0,"p",28),l(1),a()),t&2){let e=n;o(),W("",e.nodeCount.toLocaleString()," nodes \xB7 ",e.edgeCount.toLocaleString()," edges \xB7 ",e.fileCount.toLocaleString()," files")}}function xe(t,n){if(t&1&&(i(0,"div",17)(1,"h3"),l(2,"Explore the graph"),a(),i(3,"p"),l(4,"Search for a function, method or class to start. The graph renders the symbol with its callers, callees and any linked specs."),a(),g(5,_e,2,3,"p",28),a()),t&2){let e,r=c(2);o(5),u((e=r.status.state().data)?5:-1,e)}}function he(t,n){t&1&&(i(0,"div",17)(1,"p"),l(2,"Loading\u2026"),a()())}function ve(t,n){if(t&1&&(i(0,"div",17)(1,"h3"),l(2,"Couldn't load that symbol"),a(),i(3,"p"),l(4),a()()),t&2){let e=c(2);o(4),m(e.nodeDetail.state().error)}}function fe(t,n){if(t&1&&(i(0,"div",17)(1,"p"),l(2),a()()),t&2){let e=c(2);o(2),z('No match for "',e.selectedSymbol(),'".')}}function Ce(t,n){if(t&1&&(i(0,"div",32),p(1,"span",42),i(2,"span",43),l(3),a()()),t&2){let e=n.$implicit;o(),T("data-kind",e),o(2),m(e)}}function be(t,n){if(t&1){let e=y();i(0,"app-graph-canvas",29),b("nodeClick",function(d){h(e);let s=c(2);return v(s.pickFromCanvas(d))}),a(),i(1,"div",30)(2,"div",31),k(3,Ce,4,2,"div",32,G),a(),p(5,"div",33),i(6,"div",34)(7,"div",35),f(),i(8,"svg",36),p(9,"line",37),a(),C(),i(10,"span",38),l(11,"implements"),a()(),i(12,"div",35),f(),i(13,"svg",36),p(14,"line",39),a(),C(),i(15,"span",38),l(16,"tests"),a()(),i(17,"div",35),f(),i(18,"svg",36),p(19,"line",40),a(),C(),i(20,"span",38),l(21,"calls"),a()(),i(22,"div",35),f(),i(23,"svg",36),p(24,"line",41),a(),C(),i(25,"span",38),l(26,"synth"),a()()()()}if(t&2){let e=c(2);x("nodes",e.visibleNodes())("edges",e.visibleEdges())("selectedId",e.selectedDetail().id)("fitKey",e.fitKey())("hiddenIds",e.hiddenIds()),o(3),S(e.kindKeys)}}function ye(t,n){if(t&1&&(i(0,"span",50),l(1),a()),t&2){let e=c();o(),m(e.startLine?"L"+e.startLine:"")}}function ke(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Signature"),a(),i(3,"pre",61),l(4),a()()),t&2){let e=c();o(4),m(e.signature)}}function Se(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Docstring"),a(),i(3,"p",62),l(4),a()()),t&2){let e=c();o(4),m(e.docstring)}}function we(t,n){if(t&1&&(i(0,"span",67),l(1),a()),t&2){let e=c().$implicit;o(),m(e.specTitle)}}function Me(t,n){if(t&1&&(i(0,"div",64),p(1,"app-state-pill",65),i(2,"span",66),l(3),a(),g(4,we,2,1,"span",67),a()),t&2){let e=n.$implicit;o(),x("state",e.state),o(2),m(e.specId),o(),u(e.specTitle?4:-1)}}function Ee(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Linked specs "),i(3,"span",63),l(4),a()(),k(5,Me,5,3,"div",64,L),a()),t&2){let e=c();o(4),m(e.linkedSpecs.length),o(),S(e.linkedSpecs)}}function Pe(t,n){if(t&1){let e=y();i(0,"button",70),b("click",function(){let d=h(e).$implicit,s=c(5);return v(s.pickResult(d))}),p(1,"app-icon",71),i(2,"span",66),l(3),a(),i(4,"span",72),l(5),a()()}if(t&2){let e=n.$implicit,r=c(5);o(),x("size",12),o(2),m(e.name),o(2),m(r.fileName(e.filePath))}}function Oe(t,n){if(t&1&&k(0,Pe,6,3,"button",69,L),t&2){let e=c(2);S(e.callers)}}function Te(t,n){t&1&&(i(0,"div",68),l(1,"No callers"),a())}function Ge(t,n){if(t&1){let e=y();i(0,"button",70),b("click",function(){let d=h(e).$implicit,s=c(5);return v(s.pickResult(d))}),p(1,"app-icon",71),i(2,"span",66),l(3),a(),i(4,"span",72),l(5),a()()}if(t&2){let e=n.$implicit,r=c(5);o(),x("size",12),o(2),m(e.name),o(2),m(r.fileName(e.filePath))}}function Ie(t,n){if(t&1&&k(0,Ge,6,3,"button",69,L),t&2){let e=c(2);S(e.callees)}}function ze(t,n){t&1&&(i(0,"div",68),l(1,"No callees"),a())}function Ke(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Callers "),i(3,"span",63),l(4),a()(),g(5,Oe,2,0)(6,Te,2,0,"div",68),a(),i(7,"div",58)(8,"div",60),l(9,"Callees "),i(10,"span",63),l(11),a()(),g(12,Ie,2,0)(13,ze,2,0,"div",68),a()),t&2){let e=c();o(4),m(e.callers.length),o(),u(e.callers.length?5:6),o(6),m(e.callees.length),o(),u(e.callees.length?12:13)}}function De(t,n){if(t&1){let e=y();i(0,"button",73),p(1,"app-icon",74),l(2," Implement "),a(),i(3,"button",14),b("click",function(){h(e);let d=c(3);return v(d.navigateToDrift())}),l(4,"Fix"),a(),i(5,"button",75),l(6,"Relink"),a()}t&2&&(o(),x("size",13))}function Ve(t,n){if(t&1){let e=y();i(0,"button",73),p(1,"app-icon",76),l(2," Reveal in editor "),a(),i(3,"button",14),b("click",function(){h(e);let d=c(3);return v(d.navigateToSpecs())}),l(4,"Open Specs"),a()}t&2&&(o(),x("size",13))}function Ne(t,n){if(t&1){let e=y();i(0,"div",44)(1,"div",45),p(2,"span",46),i(3,"div",47)(4,"div",48),l(5),a(),i(6,"div",49)(7,"span",50),l(8),a(),g(9,ye,2,1,"span",50),a()(),i(10,"button",51),b("click",function(){h(e);let d=c(2);return v(d.clearSelection())}),p(11,"app-icon",52),a()(),i(12,"div",53),p(13,"app-icon",54),i(14,"span",55),l(15),a(),p(16,"app-copy-btn",56),a()(),i(17,"div",57),g(18,ke,5,1,"div",58),g(19,Se,5,1,"div",58),g(20,Ee,7,1,"div",58),g(21,Ke,14,4),a(),i(22,"div",59),g(23,De,7,1)(24,Ve,5,1),a()}if(t&2){let e=n,r=e.kind==="spec",d=c(2).detailColor(e);o(2),I("background",d)("box-shadow","0 0 8px "+d),R("is-rect",r),o(3),m(e.name),o(2),I("color",d)("background","color-mix(in srgb, "+d+" 14%, transparent)"),o(),m(e.kind),o(),u(e.signature?9:-1),o(2),x("size",14),o(2),x("size",12),o(2),m(e.filePath),o(),x("text",e.filePath),o(2),u(e.signature?18:-1),o(),u(e.docstring?19:-1),o(),u(e.linkedSpecs&&e.linkedSpecs.length?20:-1),o(),u(r?-1:21),o(2),u(r?23:24)}}function Re(t,n){t&1&&(i(0,"span",81),l(1),a()),t&2&&(o(),z("",n.nodeCount.toLocaleString()," shown"))}function Le(t,n){if(t&1&&(i(0,"div",84),p(1,"span",86),i(2,"span",87),l(3),a(),i(4,"span",88),l(5),a()()),t&2){let e=n.$implicit,r=c(3);o(),T("data-kind",e),o(2),m(e),o(2),m(r.overviewKindCounts()[e])}}function Fe(t,n){t&1&&(i(0,"div",85),p(1,"app-state-pill",89)(2,"span",90)(3,"app-state-pill",91)(4,"span",90)(5,"app-state-pill",92)(6,"span",90),a())}function He(t,n){if(t&1&&(i(0,"div",85),p(1,"app-state-pill",89),i(2,"span",93),l(3),a(),p(4,"app-state-pill",91),i(5,"span",93),l(6),a(),p(7,"app-state-pill",92),i(8,"span",93),l(9),a()()),t&2){let e,r,d,s=c(3);o(3),m(((e=s.health.state().data)==null||e.linkHealth==null?null:e.linkHealth.verified)??0),o(3),m(((r=s.health.state().data)==null||r.linkHealth==null?null:r.linkHealth.drifted)??0),o(3),m((((d=s.health.state().data)==null||d.linkHealth==null?null:d.linkHealth.broken)??0)+(((d=s.health.state().data)==null||d.linkHealth==null?null:d.linkHealth.orphaned)??0))}}function $e(t,n){t&1&&(i(0,"div",94),f(),i(1,"svg",95),p(2,"line",96),a(),C(),p(3,"span",97),a(),i(4,"div",94),f(),i(5,"svg",95),p(6,"line",98),a(),C(),p(7,"span",97),a(),i(8,"div",94),f(),i(9,"svg",95),p(10,"line",99),a(),C(),p(11,"span",97),a(),i(12,"div",94),f(),i(13,"svg",95),p(14,"line",100),a(),C(),p(15,"span",97),a())}function je(t,n){if(t&1&&(i(0,"div",94),f(),i(1,"svg",95),p(2,"line",96),a(),C(),i(3,"span",101),l(4,"calls"),a(),i(5,"span",102),l(6),a()(),i(7,"div",94),f(),i(8,"svg",95),p(9,"line",98),a(),C(),i(10,"span",101),l(11,"implements / documents"),a(),i(12,"span",102),l(13),a()(),i(14,"div",94),f(),i(15,"svg",95),p(16,"line",99),a(),C(),i(17,"span",101),l(18,"tests"),a(),i(19,"span",102),l(20),a()(),i(21,"div",94),f(),i(22,"svg",95),p(23,"line",100),a(),C(),i(24,"span",101),l(25,"synthesized (heuristic)"),a(),i(26,"span",102),l(27),a()()),t&2){let e,r,d,s,M=c(3);o(6),m(((e=M.health.state().data)==null||e.edgeKinds==null?null:e.edgeKinds.calls)??0),o(7),m(((r=M.health.state().data)==null||r.edgeKinds==null?null:r.edgeKinds.implements)??0),o(7),m(((d=M.health.state().data)==null||d.edgeKinds==null?null:d.edgeKinds.tests)??0),o(7),m(((s=M.health.state().data)==null||s.edgeKinds==null?null:s.edgeKinds.synth)??0)}}function Be(t,n){t&1&&(i(0,"div",103),p(1,"span",104)(2,"span",105),a())}function Qe(t,n){t&1&&(i(0,"div",83)(1,"div",60),l(2,"Most connected"),a(),k(3,Be,3,0,"div",103,G),a()),t&2&&(o(3),S(X(0,de)))}function Ae(t,n){if(t&1){let e=y();i(0,"button",107),b("click",function(){let d=h(e).$implicit,s=c(4);return v(s.pickHub(d))}),p(1,"span",108),i(2,"span",109),l(3),a(),i(4,"span",110),l(5),a(),p(6,"app-icon",111),a()}if(t&2){let e=n.$implicit,r=c(4);T("aria-label",e.name+", "+e.degree+" edges"),o(),I("background",r.nodeColor(e.kind))("border-radius",e.kind==="spec"?"2px":"50%"),o(2),m(e.name),o(2),z("",e.degree," edges"),o(),x("size",11)}}function Ue(t,n){if(t&1&&(i(0,"div",83)(1,"div",60),l(2,"Most connected"),a(),k(3,Ae,7,8,"button",106,L),a()),t&2){let e=c(3);o(3),S(e.health.state().data.hubs.slice(0,8))}}function qe(t,n){if(t&1&&(i(0,"div",77),p(1,"app-icon",78),i(2,"span",79),l(3,"Graph overview"),a(),p(4,"div",80),g(5,Re,2,1,"span",81),a(),i(6,"div",57)(7,"p",82),l(8," Click any node to inspect its signature, links, callers and callees \u2014 without leaving this view. "),a(),i(9,"div",83)(10,"div",60),l(11,"Nodes by kind"),a(),k(12,Le,6,3,"div",84,G),a(),i(14,"div",83)(15,"div",60),l(16,"Spec link health"),a(),g(17,Fe,7,0,"div",85)(18,He,10,3,"div",85),a(),i(19,"div",83)(20,"div",60),l(21,"Edge types"),a(),g(22,$e,16,0)(23,je,28,4),a(),g(24,Qe,5,1,"div",83)(25,Ue,5,0,"div",83),a()),t&2){let e,r,d,s=c(2);o(),x("size",15),o(4),u((e=s.status.state().data)?5:-1,e),o(7),S(s.kindKeys),o(5),u(s.health.state().loading?17:18),o(5),u(s.health.state().loading?22:(r=s.health.state().data)!=null&&r.edgeKinds?23:-1),o(2),u(s.health.state().loading?24:!((d=s.health.state().data)==null||d.hubs==null)&&d.hubs.length?25:-1)}}function We(t,n){if(t&1){let e=y();i(0,"div",1)(1,"div",2)(2,"div",3)(3,"app-segmented",4),b("change",function(d){h(e);let s=c();return v(s.onLayoutChange(d))}),a(),p(4,"div",5),k(5,ce,5,7,"button",6,G),p(7,"div",7),i(8,"div",8)(9,"div",9),p(10,"app-icon",10),i(11,"input",11),b("input",function(d){h(e);let s=c();return v(s.onSearchInput(d.target.value))}),a(),g(12,me,1,0,"span",12),a(),g(13,ue,3,0,"div",13),a(),i(14,"button",14),b("click",function(){h(e);let d=c();return v(d.recenter())}),p(15,"app-icon",15),l(16," Recenter "),a()(),i(17,"div",16),g(18,xe,6,1,"div",17)(19,he,3,0,"div",17)(20,ve,5,1,"div",17)(21,fe,3,1,"div",17)(22,be,27,5),a()(),i(23,"aside",18),g(24,Ne,25,22)(25,qe,26,5),a()()}if(t&2){let e,r=c();o(3),x("options",r.layoutOptions)("value",r.layoutMode()),o(2),S(r.kindKeys),o(5),x("size",13),o(),x("value",r.searchInput()),o(),u(r.searchResults.state().loading?12:-1),o(),u(r.searchResults.state().data&&r.searchResults.state().data.results.length>0?13:-1),o(2),x("size",13),o(3),u(r.selectedSymbol()?r.nodeDetail.state().loading?19:r.nodeDetail.state().error?20:r.selectedDetail()?22:21:18),o(6),u((e=r.selectedDetail())?24:25,e)}}var re=class t{api=N(Y);projects=N(Z);router=N(J);status=K(this.api,()=>`/api/status${this.projects.projectQuery()}`);health=K(this.api,()=>`/api/graph/health${this.projects.projectQuery()}`);layoutMode=P("hierarchical");layoutOptions=[{value:"hierarchical",label:"Hierarchical"},{value:"force",label:"Force"},{value:"anchored",label:"Anchored"}];searchInput=P("");searchQuery=P("");searchDebounce=null;searchResults=K(this.api,()=>{let n=this.searchQuery().trim();return n.length>=2?`/api/graph/search?q=${encodeURIComponent(n)}&limit=12${this.projects.projectQuery("&")}`:null});selectedSymbol=P(null);nodeDetail=K(this.api,()=>{let n=this.selectedSymbol();return n?`/api/graph/node?symbol=${encodeURIComponent(n)}${this.projects.projectQuery("&")}`:null});selectedDetail=w(()=>this.nodeDetail.state().data?.matches?.[0]??null);filters=P({code:!0,spec:!0,route:!0,test:!0});fitKey=P(0);canvasData=w(()=>{let n=this.selectedDetail();if(!n)return{nodes:[],edges:[]};let e=this.filters(),r=_=>{let E=F(_);return e[E]},d={id:n.id,label:n.name,sub:H(n.filePath),kind:n.kind,x:0,y:0},s=(n.callers??[]).filter(_=>r(_.kind)),M=(n.callees??[]).filter(_=>r(_.kind)),$=(n.linkedSpecs??[]).filter(()=>e.spec),j=280,B=56,D=[d],V=[];return s.forEach((_,E)=>{let O=(E-(s.length-1)/2)*B;D.push(le(_,-j,O)),V.push({from:_.id,to:n.id,kind:"calls"})}),M.forEach((_,E)=>{let O=(E-(M.length-1)/2)*B;D.push(le(_,j,O)),V.push({from:n.id,to:_.id,kind:"calls"})}),$.forEach((_,E)=>{let O=(E-($.length-1)/2)*220,Q="spec:"+_.specId;D.push({id:Q,label:_.specId,sub:_.specTitle??void 0,kind:"spec",state:_.state,x:O,y:-160}),V.push({from:Q,to:n.id,kind:"implements"})}),{nodes:D,edges:V}});visibleNodes=w(()=>this.canvasData().nodes);visibleEdges=w(()=>this.canvasData().edges);hiddenIds=w(()=>{let n=this.filters(),e=new Set;for(let r of this.canvasData().nodes)n[F(r.kind)]||e.add(r.id);return e});kindCounts=w(()=>{let n={code:0,spec:0,route:0,test:0};for(let e of this.canvasData().nodes)n[F(e.kind)]++;return n});overviewKindCounts=w(()=>{let n=this.status.state().data;if(!n?.nodesByKind)return{code:0,spec:0,route:0,test:0};let e=n.nodesByKind;return{code:(e.function??0)+(e.method??0)+(e.class??0)+(e.variable??0)+(e.constant??0)+(e.type_alias??0)+(e.interface??0)+(e.struct??0)+(e.enum??0)+(e.property??0)+(e.field??0)+(e.file??0)+(e.module??0)+(e.namespace??0)+(e.component??0),spec:e.spec??0,route:e.route??0,test:e.test??0}});kindKeys=["code","spec","route","test"];isFilterActive(n){return this.filters()[n]}countFor(n){return this.kindCounts()[n]}chipColor(n){switch(n){case"spec":return"var(--node-spec)";case"route":return"var(--node-route)";case"test":return"var(--node-test)";default:return"var(--node-code)"}}onSearchInput(n){this.searchInput.set(n),this.searchDebounce&&clearTimeout(this.searchDebounce),this.searchDebounce=setTimeout(()=>this.searchQuery.set(n),180)}pickResult(n){this.searchInput.set(n.name),this.searchQuery.set(""),this.selectedSymbol.set(n.name)}pickFromCanvas(n){let e=this.selectedDetail();if(!e||n===e.id)return;let d=[...e.callers??[],...e.callees??[]].find(s=>s.id===n);d&&(this.selectedSymbol.set(d.name),this.fitKey.update(s=>s+1))}toggleFilter(n){this.filters.update(e=>U(A({},e),{[n]:!e[n]})),this.fitKey.update(e=>e+1)}recenter(){this.fitKey.update(n=>n+1)}clearSelection(){this.selectedSymbol.set(null),this.searchInput.set("")}onLayoutChange(n){this.layoutMode.set(n),this.fitKey.update(e=>e+1)}shortPath(n){return H(n)}fileName(n){return n?n.split("/").pop()??"":""}kindLabel(n){return n.charAt(0).toUpperCase()+n.slice(1)}navigateToSpecs(){this.router.navigate(["/specs"])}navigateToDrift(){this.router.navigate(["/drift"])}nodeColor(n){return n==="spec"?"var(--node-spec)":n==="route"?"var(--node-route)":n==="test"?"var(--node-test)":"var(--node-code)"}pickHub(n){this.selectedSymbol.set(n.name),this.fitKey.update(e=>e+1)}detailColor(n){if(n.kind==="spec"){let e=n.linkedSpecs??[],r=e.some(s=>s.state==="broken"||s.state==="orphaned"),d=!r&&e.some(s=>s.state==="drifted");return r?"var(--error)":d?"var(--warn)":"var(--node-spec)"}return n.kind==="test"?"var(--node-test)":n.kind==="route"?"var(--node-route)":"var(--node-code)"}static \u0275fac=function(e){return new(e||t)};static \u0275cmp=q({type:t,selectors:[["app-graph"]],decls:2,vars:1,consts:[["surface","The graph"],[1,"gp-root"],[1,"gp-main"],[1,"gp-toolbar"],["size","sm",3,"change","options","value"],[1,"gp-divider"],["type","button",1,"gp-chip",3,"is-active","--chip-color"],[1,"gp-spacer"],[1,"gp-search"],[1,"gp-search-inner"],["name","search",1,"gp-search-icon",3,"size"],["type","text","placeholder","Fuzzy symbol search\u2026","aria-label","Symbol search",3,"input","value"],["aria-hidden","true",1,"gp-spinner"],["role","listbox",1,"gp-results"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","recenter",3,"size"],[1,"gp-canvas-wrap"],[1,"gp-empty"],[1,"gp-panel"],["type","button",1,"gp-chip",3,"click"],[1,"gp-chip-dot"],[1,"gp-chip-count"],["type","button",1,"gp-result"],["type","button",1,"gp-result",3,"click"],[1,"gp-result-dot"],[1,"gp-result-name","mono"],[1,"gp-result-kind"],[1,"gp-result-path","mono"],[1,"gp-stats"],[3,"nodeClick","nodes","edges","selectedId","fitKey","hiddenIds"],[1,"gp-legend"],[1,"gp-legend-kinds"],[1,"gp-legend-item"],[1,"gp-legend-sep"],[1,"gp-legend-edges"],[1,"gp-legend-edge-row"],["width","16","height","8"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--node-spec)","stroke-width","1.6"],[1,"secondary"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--node-test)","stroke-width","1.6"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--text-muted)","stroke-width","1.6"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--text-muted)","stroke-width","1.6","stroke-dasharray","4 3"],[1,"gp-legend-dot"],[1,"secondary",2,"text-transform","capitalize"],[1,"gp-panel-header"],[1,"gp-panel-header-inner"],[1,"gp-node-dot"],[1,"grow",2,"min-width","0"],[1,"mono","gp-panel-name"],[1,"row","gap-6",2,"margin-top","3px"],[1,"pill"],["type","button","aria-label","Close panel",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"gp-panel-path","row","gap-6"],["name","folder",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","secondary","gp-path-text"],[3,"text"],[1,"gp-panel-body","scroll-y"],[1,"gp-section"],[1,"gp-panel-footer"],[1,"eyebrow","gp-eyebrow"],[1,"gp-code","mono"],[1,"secondary",2,"font-size","12px","line-height","1.6","margin","0"],[1,"muted",2,"font-weight","400","margin-left","5px"],[1,"gp-link-row"],[3,"state"],[1,"mono","grow","gp-link-text"],[1,"muted",2,"font-size","10px","flex-shrink","0","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","max-width","120px"],[1,"muted",2,"font-size","12px","padding","4px 8px"],["type","button",1,"gp-node-link"],["type","button",1,"gp-node-link",3,"click"],["name","box",2,"color","var(--node-code)","flex-shrink","0",3,"size"],[1,"mono","muted","gp-link-file"],["type","button",1,"btn","btn-primary","btn-sm","grow",2,"justify-content","center"],["name","play",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","reveal",3,"size"],[1,"gp-panel-header","gp-overview-head"],["name","graph",2,"color","var(--accent)",3,"size"],[2,"font-weight","600","font-size","13.5px"],[1,"grow"],[1,"mono","muted",2,"font-size","11px"],[1,"secondary",2,"font-size","12px","line-height","1.55","margin","0 0 18px"],[1,"gp-section-plain"],[1,"gp-kind-row"],[1,"row","gap-6",2,"flex-wrap","wrap","align-items","center"],[1,"gp-kind-dot"],[1,"grow",2,"font-size","12.5px","text-transform","capitalize"],[1,"mono","tabular",2,"font-size","12.5px","font-weight","600"],["state","verified"],["aria-hidden","true",1,"gp-skel","gp-skel-sm"],["state","drifted"],["state","broken"],[1,"mono","tabular","muted",2,"font-size","11px","align-self","center"],[1,"gp-edge-row"],["width","20","height","8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--text-muted)","stroke-width","1.8"],["aria-hidden","true",1,"gp-skel","gp-skel-lg"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--node-spec)","stroke-width","1.8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--node-test)","stroke-width","1.8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--text-muted)","stroke-width","1.8","stroke-dasharray","4 3"],[1,"grow","secondary",2,"font-size","12px"],[1,"mono","tabular","muted",2,"font-size","11px"],["aria-hidden","true",1,"gp-hub-row"],[1,"gp-hub-dot","gp-skel-dot"],["aria-hidden","true",1,"gp-skel","gp-skel-hub"],["type","button",1,"gp-hub-row"],["type","button",1,"gp-hub-row",3,"click"],[1,"gp-hub-dot"],[1,"mono","grow","gp-hub-name"],[1,"muted","gp-hub-degree"],["name","chevron-right",2,"color","var(--text-muted)","flex-shrink","0",3,"size"]],template:function(e,r){e&1&&g(0,se,1,0,"app-pick-project-empty",0)(1,We,26,9,"div",1),e&2&&u(r.status.state().noProject?0:1)},dependencies:[ne,ie,ee,te,ae,oe],styles:["[_nghost-%COMP%]{display:contents}.gp-root[_ngcontent-%COMP%]{flex:1;display:flex;min-height:0;min-width:0}.gp-main[_ngcontent-%COMP%]{flex:1;min-width:0;display:flex;flex-direction:column}.gp-toolbar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;padding:9px 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel-2, var(--bg-panel));flex-wrap:wrap;flex-shrink:0}.gp-divider[_ngcontent-%COMP%]{width:1px;height:20px;background:var(--border-subtle);flex-shrink:0}.gp-chip[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;height:26px;padding:0 10px;border-radius:999px;font-size:11.5px;font-weight:500;cursor:pointer;border:1px solid var(--border-subtle);background:var(--bg-panel);color:var(--text-secondary);transition:all .1s}.gp-chip.is-active[_ngcontent-%COMP%]{border-color:transparent;background:color-mix(in srgb,var(--chip-color, var(--accent)) 22%,var(--bg-panel));color:var(--chip-color, var(--accent))}.gp-chip-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%}.gp-chip-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code)}.gp-chip-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-chip-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route)}.gp-chip-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test)}.gp-chip-count[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted);font-variant-numeric:tabular-nums}.gp-spacer[_ngcontent-%COMP%]{flex:1}.gp-search[_ngcontent-%COMP%]{position:relative;flex-shrink:0}.gp-search-inner[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;height:28px;padding:0 10px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;width:220px}.gp-search-inner[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{flex:1;background:transparent;border:none;outline:none;color:var(--text-primary);font-size:12px;font-family:var(--font-mono)}.gp-search-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.gp-spinner[_ngcontent-%COMP%]{width:12px;height:12px;border:2px solid var(--border-subtle);border-top-color:var(--accent);border-radius:50%;animation:_ngcontent-%COMP%_gp-spin .7s linear infinite;flex-shrink:0}@keyframes _ngcontent-%COMP%_gp-spin{to{transform:rotate(360deg)}}.gp-results[_ngcontent-%COMP%]{position:absolute;top:32px;left:0;right:0;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:8px;box-shadow:var(--shadow-pop, 0 12px 28px rgba(0, 0, 0, .5));padding:5px;z-index:30;max-height:320px;overflow-y:auto}.gp-result[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border-radius:5px;background:transparent;border:none;cursor:pointer;font:inherit;color:var(--text-primary);text-align:left}.gp-result[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-result-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%;background:var(--node-code);flex-shrink:0}.gp-result-dot.is-spec[_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-result-dot.is-route[_ngcontent-%COMP%]{background:var(--node-route)}.gp-result-dot.is-test[_ngcontent-%COMP%]{background:var(--node-test)}.gp-result-name[_ngcontent-%COMP%]{font-size:12px;flex-shrink:0}.gp-result-kind[_ngcontent-%COMP%]{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}.gp-result-path[_ngcontent-%COMP%]{flex:1;text-align:right;font-size:10px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-canvas-wrap[_ngcontent-%COMP%]{flex:1;min-height:0;position:relative;display:flex}.gp-canvas-wrap[_ngcontent-%COMP%] app-graph-canvas[_ngcontent-%COMP%]{flex:1;min-height:0}.gp-empty[_ngcontent-%COMP%]{flex:1;display:grid;place-items:center;text-align:center;padding:60px 24px;background:var(--bg-canvas-2, var(--bg-canvas))}.gp-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{font-size:18px;font-weight:600;margin:0 0 8px}.gp-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{color:var(--text-secondary);font-size:13.5px;line-height:1.6;margin:0;max-width:520px}.gp-stats[_ngcontent-%COMP%]{margin-top:18px!important;font-family:var(--font-mono);font-size:11.5px!important;color:var(--text-muted)!important}.gp-legend[_ngcontent-%COMP%]{position:absolute;top:14px;left:14px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;max-width:70%;background:color-mix(in srgb,var(--bg-panel) 86%,transparent);border:1px solid var(--border-subtle);border-radius:8px;padding:6px 10px;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);font-size:11px;pointer-events:none;z-index:3}.gp-legend-kinds[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px}.gp-legend-item[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px}.gp-legend-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.gp-legend-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code)}.gp-legend-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-legend-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route)}.gp-legend-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test)}.gp-legend-sep[_ngcontent-%COMP%]{width:1px;height:16px;background:var(--border-subtle);flex-shrink:0}.gp-legend-edges[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.gp-legend-edge-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px}.gp-panel[_ngcontent-%COMP%]{width:360px;flex-shrink:0;border-left:1px solid var(--border-subtle);background:var(--bg-panel);display:flex;flex-direction:column;overflow:hidden}.gp-panel-header[_ngcontent-%COMP%]{padding:12px 14px;border-bottom:1px solid var(--border-subtle);flex-shrink:0}.gp-panel-header-inner[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px}.gp-overview-head[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.gp-node-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}.gp-node-dot.is-rect[_ngcontent-%COMP%]{border-radius:2px}.gp-panel-name[_ngcontent-%COMP%]{font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-panel-path[_ngcontent-%COMP%]{margin-top:8px;font-size:11.5px;color:var(--text-secondary)}.gp-path-text[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.gp-panel-body[_ngcontent-%COMP%]{flex:1;padding:14px;overflow-y:auto;display:flex;flex-direction:column;gap:18px}.gp-section[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px}.gp-section-plain[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px}.gp-eyebrow[_ngcontent-%COMP%]{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);margin-bottom:6px}.gp-code[_ngcontent-%COMP%]{margin:0;font-size:11.5px;line-height:1.6;color:var(--text-secondary);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word}.gp-link-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;border:1px solid var(--border-subtle);margin-bottom:5px;font-size:11.5px}.gp-link-text[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}.gp-node-link[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:5px 8px;border-radius:6px;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;text-align:left;font-size:12px}.gp-node-link[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-link-file[_ngcontent-%COMP%]{font-size:10px;flex-shrink:0}.gp-edge-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:4px 0}.gp-kind-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:5px 0}.gp-kind-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%;flex-shrink:0}.gp-kind-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code);box-shadow:0 0 6px var(--node-code)}.gp-kind-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px;box-shadow:0 0 6px var(--node-spec)}.gp-kind-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route);box-shadow:0 0 6px var(--node-route)}.gp-kind-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test);box-shadow:0 0 6px var(--node-test)}.gp-panel-footer[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:12px 14px;border-top:1px solid var(--border-subtle);flex-shrink:0}.gp-hub-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:5px 8px;border-radius:6px;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;text-align:left}.gp-hub-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-hub-dot[_ngcontent-%COMP%]{width:8px;height:8px;flex-shrink:0}.gp-hub-name[_ngcontent-%COMP%]{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-hub-degree[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted);flex-shrink:0;font-variant-numeric:tabular-nums}@keyframes _ngcontent-%COMP%_gp-skel-pulse{0%,to{opacity:.35}50%{opacity:.7}}.gp-skel[_ngcontent-%COMP%]{display:inline-block;background:var(--border-subtle);border-radius:4px;animation:_ngcontent-%COMP%_gp-skel-pulse 1.4s ease-in-out infinite}.gp-skel-sm[_ngcontent-%COMP%]{width:24px;height:12px}.gp-skel-lg[_ngcontent-%COMP%]{width:80px;height:12px;flex:1}.gp-skel-hub[_ngcontent-%COMP%]{width:120px;height:12px;flex:1}.gp-skel-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--border-subtle);animation:_ngcontent-%COMP%_gp-skel-pulse 1.4s ease-in-out infinite}.grow[_ngcontent-%COMP%]{flex:1}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}"],changeDetection:0})};function le(t,n,e){return{id:t.id,label:t.name,sub:H(t.filePath),kind:t.kind,x:n,y:e}}function H(t){return t?t.split("/").slice(-2).join("/"):""}function F(t){return t==="spec"?"spec":t==="route"?"route":t==="test"?"test":"code"}export{re as Graph};
1
+ import{a as oe}from"./chunk-R5W2MDZN.js";import{b as ae}from"./chunk-HZA6NEAB.js";import{a as ie}from"./chunk-WDU3WICG.js";import{a as ne}from"./chunk-2GBEK2GM.js";import{a as te}from"./chunk-SUZYBYDW.js";import{c as J}from"./chunk-SHPTC4RL.js";import{c as K}from"./chunk-GR72OOCN.js";import{a as Z}from"./chunk-7RNS77UP.js";import{a as Y}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as y,I as N,Ia as b,Ka as c,M as h,N as v,O as f,P as C,Ta as I,Ua as R,Va as l,W as P,Wa as m,Xa as z,Za as W,bb as X,ea as o,ka as q,lb as w,qa as T,ra as g,sa as u,ua as G,va as k,wa as S,xa as x,ya as i,za as a,zb as ee}from"./chunk-PDN6QYGJ.js";import{a as A,b as U}from"./chunk-Q7L6LLAK.js";var de=()=>[1,2,3,4],pe=(t,n)=>n.node.id,L=(t,n)=>n.id;function se(t,n){t&1&&p(0,"app-pick-project-empty",0)}function ce(t,n){if(t&1){let e=y();i(0,"button",19),b("click",function(){let d=h(e).$implicit,s=c(2);return v(s.toggleFilter(d))}),p(1,"span",20),l(2),i(3,"span",21),l(4),a()()}if(t&2){let e=n.$implicit,r=c(2);I("--chip-color",r.chipColor(e)),R("is-active",r.isFilterActive(e)),o(),T("data-kind",e),o(),z(" ",r.kindLabel(e)," "),o(2),m(r.countFor(e))}}function me(t,n){t&1&&p(0,"span",12)}function ge(t,n){if(t&1){let e=y();i(0,"button",23),b("click",function(){let d=h(e).$implicit,s=c(3);return v(s.pickResult(d.node))}),p(1,"span",24),i(2,"span",25),l(3),a(),i(4,"span",26),l(5),a(),i(6,"span",27),l(7),a()()}if(t&2){let e=n.$implicit,r=c(3);o(),R("is-spec",e.node.kind==="spec")("is-route",e.node.kind==="route")("is-test",e.node.kind==="test"),o(2),m(e.node.name),o(2),m(e.node.kind),o(2),m(r.shortPath(e.node.filePath))}}function ue(t,n){if(t&1&&(i(0,"div",13),k(1,ge,8,9,"button",22,pe),a()),t&2){let e=c(2);o(),S(e.searchResults.state().data.results)}}function _e(t,n){if(t&1&&(i(0,"p",28),l(1),a()),t&2){let e=n;o(),W("",e.nodeCount.toLocaleString()," nodes \xB7 ",e.edgeCount.toLocaleString()," edges \xB7 ",e.fileCount.toLocaleString()," files")}}function xe(t,n){if(t&1&&(i(0,"div",17)(1,"h3"),l(2,"Explore the graph"),a(),i(3,"p"),l(4,"Search for a function, method or class to start. The graph renders the symbol with its callers, callees and any linked specs."),a(),g(5,_e,2,3,"p",28),a()),t&2){let e,r=c(2);o(5),u((e=r.status.state().data)?5:-1,e)}}function he(t,n){t&1&&(i(0,"div",17)(1,"p"),l(2,"Loading\u2026"),a()())}function ve(t,n){if(t&1&&(i(0,"div",17)(1,"h3"),l(2,"Couldn't load that symbol"),a(),i(3,"p"),l(4),a()()),t&2){let e=c(2);o(4),m(e.nodeDetail.state().error)}}function fe(t,n){if(t&1&&(i(0,"div",17)(1,"p"),l(2),a()()),t&2){let e=c(2);o(2),z('No match for "',e.selectedSymbol(),'".')}}function Ce(t,n){if(t&1&&(i(0,"div",32),p(1,"span",42),i(2,"span",43),l(3),a()()),t&2){let e=n.$implicit;o(),T("data-kind",e),o(2),m(e)}}function be(t,n){if(t&1){let e=y();i(0,"app-graph-canvas",29),b("nodeClick",function(d){h(e);let s=c(2);return v(s.pickFromCanvas(d))}),a(),i(1,"div",30)(2,"div",31),k(3,Ce,4,2,"div",32,G),a(),p(5,"div",33),i(6,"div",34)(7,"div",35),f(),i(8,"svg",36),p(9,"line",37),a(),C(),i(10,"span",38),l(11,"implements"),a()(),i(12,"div",35),f(),i(13,"svg",36),p(14,"line",39),a(),C(),i(15,"span",38),l(16,"tests"),a()(),i(17,"div",35),f(),i(18,"svg",36),p(19,"line",40),a(),C(),i(20,"span",38),l(21,"calls"),a()(),i(22,"div",35),f(),i(23,"svg",36),p(24,"line",41),a(),C(),i(25,"span",38),l(26,"synth"),a()()()()}if(t&2){let e=c(2);x("nodes",e.visibleNodes())("edges",e.visibleEdges())("selectedId",e.selectedDetail().id)("fitKey",e.fitKey())("hiddenIds",e.hiddenIds()),o(3),S(e.kindKeys)}}function ye(t,n){if(t&1&&(i(0,"span",50),l(1),a()),t&2){let e=c();o(),m(e.startLine?"L"+e.startLine:"")}}function ke(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Signature"),a(),i(3,"pre",61),l(4),a()()),t&2){let e=c();o(4),m(e.signature)}}function Se(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Docstring"),a(),i(3,"p",62),l(4),a()()),t&2){let e=c();o(4),m(e.docstring)}}function we(t,n){if(t&1&&(i(0,"span",67),l(1),a()),t&2){let e=c().$implicit;o(),m(e.specTitle)}}function Me(t,n){if(t&1&&(i(0,"div",64),p(1,"app-state-pill",65),i(2,"span",66),l(3),a(),g(4,we,2,1,"span",67),a()),t&2){let e=n.$implicit;o(),x("state",e.state),o(2),m(e.specId),o(),u(e.specTitle?4:-1)}}function Ee(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Linked specs "),i(3,"span",63),l(4),a()(),k(5,Me,5,3,"div",64,L),a()),t&2){let e=c();o(4),m(e.linkedSpecs.length),o(),S(e.linkedSpecs)}}function Pe(t,n){if(t&1){let e=y();i(0,"button",70),b("click",function(){let d=h(e).$implicit,s=c(5);return v(s.pickResult(d))}),p(1,"app-icon",71),i(2,"span",66),l(3),a(),i(4,"span",72),l(5),a()()}if(t&2){let e=n.$implicit,r=c(5);o(),x("size",12),o(2),m(e.name),o(2),m(r.fileName(e.filePath))}}function Oe(t,n){if(t&1&&k(0,Pe,6,3,"button",69,L),t&2){let e=c(2);S(e.callers)}}function Te(t,n){t&1&&(i(0,"div",68),l(1,"No callers"),a())}function Ge(t,n){if(t&1){let e=y();i(0,"button",70),b("click",function(){let d=h(e).$implicit,s=c(5);return v(s.pickResult(d))}),p(1,"app-icon",71),i(2,"span",66),l(3),a(),i(4,"span",72),l(5),a()()}if(t&2){let e=n.$implicit,r=c(5);o(),x("size",12),o(2),m(e.name),o(2),m(r.fileName(e.filePath))}}function Ie(t,n){if(t&1&&k(0,Ge,6,3,"button",69,L),t&2){let e=c(2);S(e.callees)}}function ze(t,n){t&1&&(i(0,"div",68),l(1,"No callees"),a())}function Ke(t,n){if(t&1&&(i(0,"div",58)(1,"div",60),l(2,"Callers "),i(3,"span",63),l(4),a()(),g(5,Oe,2,0)(6,Te,2,0,"div",68),a(),i(7,"div",58)(8,"div",60),l(9,"Callees "),i(10,"span",63),l(11),a()(),g(12,Ie,2,0)(13,ze,2,0,"div",68),a()),t&2){let e=c();o(4),m(e.callers.length),o(),u(e.callers.length?5:6),o(6),m(e.callees.length),o(),u(e.callees.length?12:13)}}function De(t,n){if(t&1){let e=y();i(0,"button",73),p(1,"app-icon",74),l(2," Implement "),a(),i(3,"button",14),b("click",function(){h(e);let d=c(3);return v(d.navigateToDrift())}),l(4,"Fix"),a(),i(5,"button",75),l(6,"Relink"),a()}t&2&&(o(),x("size",13))}function Ve(t,n){if(t&1){let e=y();i(0,"button",73),p(1,"app-icon",76),l(2," Reveal in editor "),a(),i(3,"button",14),b("click",function(){h(e);let d=c(3);return v(d.navigateToSpecs())}),l(4,"Open Specs"),a()}t&2&&(o(),x("size",13))}function Ne(t,n){if(t&1){let e=y();i(0,"div",44)(1,"div",45),p(2,"span",46),i(3,"div",47)(4,"div",48),l(5),a(),i(6,"div",49)(7,"span",50),l(8),a(),g(9,ye,2,1,"span",50),a()(),i(10,"button",51),b("click",function(){h(e);let d=c(2);return v(d.clearSelection())}),p(11,"app-icon",52),a()(),i(12,"div",53),p(13,"app-icon",54),i(14,"span",55),l(15),a(),p(16,"app-copy-btn",56),a()(),i(17,"div",57),g(18,ke,5,1,"div",58),g(19,Se,5,1,"div",58),g(20,Ee,7,1,"div",58),g(21,Ke,14,4),a(),i(22,"div",59),g(23,De,7,1)(24,Ve,5,1),a()}if(t&2){let e=n,r=e.kind==="spec",d=c(2).detailColor(e);o(2),I("background",d)("box-shadow","0 0 8px "+d),R("is-rect",r),o(3),m(e.name),o(2),I("color",d)("background","color-mix(in srgb, "+d+" 14%, transparent)"),o(),m(e.kind),o(),u(e.signature?9:-1),o(2),x("size",14),o(2),x("size",12),o(2),m(e.filePath),o(),x("text",e.filePath),o(2),u(e.signature?18:-1),o(),u(e.docstring?19:-1),o(),u(e.linkedSpecs&&e.linkedSpecs.length?20:-1),o(),u(r?-1:21),o(2),u(r?23:24)}}function Re(t,n){t&1&&(i(0,"span",81),l(1),a()),t&2&&(o(),z("",n.nodeCount.toLocaleString()," shown"))}function Le(t,n){if(t&1&&(i(0,"div",84),p(1,"span",86),i(2,"span",87),l(3),a(),i(4,"span",88),l(5),a()()),t&2){let e=n.$implicit,r=c(3);o(),T("data-kind",e),o(2),m(e),o(2),m(r.overviewKindCounts()[e])}}function Fe(t,n){t&1&&(i(0,"div",85),p(1,"app-state-pill",89)(2,"span",90)(3,"app-state-pill",91)(4,"span",90)(5,"app-state-pill",92)(6,"span",90),a())}function He(t,n){if(t&1&&(i(0,"div",85),p(1,"app-state-pill",89),i(2,"span",93),l(3),a(),p(4,"app-state-pill",91),i(5,"span",93),l(6),a(),p(7,"app-state-pill",92),i(8,"span",93),l(9),a()()),t&2){let e,r,d,s=c(3);o(3),m(((e=s.health.state().data)==null||e.linkHealth==null?null:e.linkHealth.verified)??0),o(3),m(((r=s.health.state().data)==null||r.linkHealth==null?null:r.linkHealth.drifted)??0),o(3),m((((d=s.health.state().data)==null||d.linkHealth==null?null:d.linkHealth.broken)??0)+(((d=s.health.state().data)==null||d.linkHealth==null?null:d.linkHealth.orphaned)??0))}}function $e(t,n){t&1&&(i(0,"div",94),f(),i(1,"svg",95),p(2,"line",96),a(),C(),p(3,"span",97),a(),i(4,"div",94),f(),i(5,"svg",95),p(6,"line",98),a(),C(),p(7,"span",97),a(),i(8,"div",94),f(),i(9,"svg",95),p(10,"line",99),a(),C(),p(11,"span",97),a(),i(12,"div",94),f(),i(13,"svg",95),p(14,"line",100),a(),C(),p(15,"span",97),a())}function je(t,n){if(t&1&&(i(0,"div",94),f(),i(1,"svg",95),p(2,"line",96),a(),C(),i(3,"span",101),l(4,"calls"),a(),i(5,"span",102),l(6),a()(),i(7,"div",94),f(),i(8,"svg",95),p(9,"line",98),a(),C(),i(10,"span",101),l(11,"implements / documents"),a(),i(12,"span",102),l(13),a()(),i(14,"div",94),f(),i(15,"svg",95),p(16,"line",99),a(),C(),i(17,"span",101),l(18,"tests"),a(),i(19,"span",102),l(20),a()(),i(21,"div",94),f(),i(22,"svg",95),p(23,"line",100),a(),C(),i(24,"span",101),l(25,"synthesized (heuristic)"),a(),i(26,"span",102),l(27),a()()),t&2){let e,r,d,s,M=c(3);o(6),m(((e=M.health.state().data)==null||e.edgeKinds==null?null:e.edgeKinds.calls)??0),o(7),m(((r=M.health.state().data)==null||r.edgeKinds==null?null:r.edgeKinds.implements)??0),o(7),m(((d=M.health.state().data)==null||d.edgeKinds==null?null:d.edgeKinds.tests)??0),o(7),m(((s=M.health.state().data)==null||s.edgeKinds==null?null:s.edgeKinds.synth)??0)}}function Be(t,n){t&1&&(i(0,"div",103),p(1,"span",104)(2,"span",105),a())}function Qe(t,n){t&1&&(i(0,"div",83)(1,"div",60),l(2,"Most connected"),a(),k(3,Be,3,0,"div",103,G),a()),t&2&&(o(3),S(X(0,de)))}function Ae(t,n){if(t&1){let e=y();i(0,"button",107),b("click",function(){let d=h(e).$implicit,s=c(4);return v(s.pickHub(d))}),p(1,"span",108),i(2,"span",109),l(3),a(),i(4,"span",110),l(5),a(),p(6,"app-icon",111),a()}if(t&2){let e=n.$implicit,r=c(4);T("aria-label",e.name+", "+e.degree+" edges"),o(),I("background",r.nodeColor(e.kind))("border-radius",e.kind==="spec"?"2px":"50%"),o(2),m(e.name),o(2),z("",e.degree," edges"),o(),x("size",11)}}function Ue(t,n){if(t&1&&(i(0,"div",83)(1,"div",60),l(2,"Most connected"),a(),k(3,Ae,7,8,"button",106,L),a()),t&2){let e=c(3);o(3),S(e.health.state().data.hubs.slice(0,8))}}function qe(t,n){if(t&1&&(i(0,"div",77),p(1,"app-icon",78),i(2,"span",79),l(3,"Graph overview"),a(),p(4,"div",80),g(5,Re,2,1,"span",81),a(),i(6,"div",57)(7,"p",82),l(8," Click any node to inspect its signature, links, callers and callees \u2014 without leaving this view. "),a(),i(9,"div",83)(10,"div",60),l(11,"Nodes by kind"),a(),k(12,Le,6,3,"div",84,G),a(),i(14,"div",83)(15,"div",60),l(16,"Spec link health"),a(),g(17,Fe,7,0,"div",85)(18,He,10,3,"div",85),a(),i(19,"div",83)(20,"div",60),l(21,"Edge types"),a(),g(22,$e,16,0)(23,je,28,4),a(),g(24,Qe,5,1,"div",83)(25,Ue,5,0,"div",83),a()),t&2){let e,r,d,s=c(2);o(),x("size",15),o(4),u((e=s.status.state().data)?5:-1,e),o(7),S(s.kindKeys),o(5),u(s.health.state().loading?17:18),o(5),u(s.health.state().loading?22:(r=s.health.state().data)!=null&&r.edgeKinds?23:-1),o(2),u(s.health.state().loading?24:!((d=s.health.state().data)==null||d.hubs==null)&&d.hubs.length?25:-1)}}function We(t,n){if(t&1){let e=y();i(0,"div",1)(1,"div",2)(2,"div",3)(3,"app-segmented",4),b("change",function(d){h(e);let s=c();return v(s.onLayoutChange(d))}),a(),p(4,"div",5),k(5,ce,5,7,"button",6,G),p(7,"div",7),i(8,"div",8)(9,"div",9),p(10,"app-icon",10),i(11,"input",11),b("input",function(d){h(e);let s=c();return v(s.onSearchInput(d.target.value))}),a(),g(12,me,1,0,"span",12),a(),g(13,ue,3,0,"div",13),a(),i(14,"button",14),b("click",function(){h(e);let d=c();return v(d.recenter())}),p(15,"app-icon",15),l(16," Recenter "),a()(),i(17,"div",16),g(18,xe,6,1,"div",17)(19,he,3,0,"div",17)(20,ve,5,1,"div",17)(21,fe,3,1,"div",17)(22,be,27,5),a()(),i(23,"aside",18),g(24,Ne,25,22)(25,qe,26,5),a()()}if(t&2){let e,r=c();o(3),x("options",r.layoutOptions)("value",r.layoutMode()),o(2),S(r.kindKeys),o(5),x("size",13),o(),x("value",r.searchInput()),o(),u(r.searchResults.state().loading?12:-1),o(),u(r.searchResults.state().data&&r.searchResults.state().data.results.length>0?13:-1),o(2),x("size",13),o(3),u(r.selectedSymbol()?r.nodeDetail.state().loading?19:r.nodeDetail.state().error?20:r.selectedDetail()?22:21:18),o(6),u((e=r.selectedDetail())?24:25,e)}}var re=class t{api=N(Y);projects=N(Z);router=N(J);status=K(this.api,()=>`/api/status${this.projects.projectQuery()}`);health=K(this.api,()=>`/api/graph/health${this.projects.projectQuery()}`);layoutMode=P("hierarchical");layoutOptions=[{value:"hierarchical",label:"Hierarchical"},{value:"force",label:"Force"},{value:"anchored",label:"Anchored"}];searchInput=P("");searchQuery=P("");searchDebounce=null;searchResults=K(this.api,()=>{let n=this.searchQuery().trim();return n.length>=2?`/api/graph/search?q=${encodeURIComponent(n)}&limit=12${this.projects.projectQuery("&")}`:null});selectedSymbol=P(null);nodeDetail=K(this.api,()=>{let n=this.selectedSymbol();return n?`/api/graph/node?symbol=${encodeURIComponent(n)}${this.projects.projectQuery("&")}`:null});selectedDetail=w(()=>this.nodeDetail.state().data?.matches?.[0]??null);filters=P({code:!0,spec:!0,route:!0,test:!0});fitKey=P(0);canvasData=w(()=>{let n=this.selectedDetail();if(!n)return{nodes:[],edges:[]};let e=this.filters(),r=_=>{let E=F(_);return e[E]},d={id:n.id,label:n.name,sub:H(n.filePath),kind:n.kind,x:0,y:0},s=(n.callers??[]).filter(_=>r(_.kind)),M=(n.callees??[]).filter(_=>r(_.kind)),$=(n.linkedSpecs??[]).filter(()=>e.spec),j=280,B=56,D=[d],V=[];return s.forEach((_,E)=>{let O=(E-(s.length-1)/2)*B;D.push(le(_,-j,O)),V.push({from:_.id,to:n.id,kind:"calls"})}),M.forEach((_,E)=>{let O=(E-(M.length-1)/2)*B;D.push(le(_,j,O)),V.push({from:n.id,to:_.id,kind:"calls"})}),$.forEach((_,E)=>{let O=(E-($.length-1)/2)*220,Q="spec:"+_.specId;D.push({id:Q,label:_.specId,sub:_.specTitle??void 0,kind:"spec",state:_.state,x:O,y:-160}),V.push({from:Q,to:n.id,kind:"implements"})}),{nodes:D,edges:V}});visibleNodes=w(()=>this.canvasData().nodes);visibleEdges=w(()=>this.canvasData().edges);hiddenIds=w(()=>{let n=this.filters(),e=new Set;for(let r of this.canvasData().nodes)n[F(r.kind)]||e.add(r.id);return e});kindCounts=w(()=>{let n={code:0,spec:0,route:0,test:0};for(let e of this.canvasData().nodes)n[F(e.kind)]++;return n});overviewKindCounts=w(()=>{let n=this.status.state().data;if(!n?.nodesByKind)return{code:0,spec:0,route:0,test:0};let e=n.nodesByKind;return{code:(e.function??0)+(e.method??0)+(e.class??0)+(e.variable??0)+(e.constant??0)+(e.type_alias??0)+(e.interface??0)+(e.struct??0)+(e.enum??0)+(e.property??0)+(e.field??0)+(e.file??0)+(e.module??0)+(e.namespace??0)+(e.component??0),spec:e.spec??0,route:e.route??0,test:e.test??0}});kindKeys=["code","spec","route","test"];isFilterActive(n){return this.filters()[n]}countFor(n){return this.kindCounts()[n]}chipColor(n){switch(n){case"spec":return"var(--node-spec)";case"route":return"var(--node-route)";case"test":return"var(--node-test)";default:return"var(--node-code)"}}onSearchInput(n){this.searchInput.set(n),this.searchDebounce&&clearTimeout(this.searchDebounce),this.searchDebounce=setTimeout(()=>this.searchQuery.set(n),180)}pickResult(n){this.searchInput.set(n.name),this.searchQuery.set(""),this.selectedSymbol.set(n.name)}pickFromCanvas(n){let e=this.selectedDetail();if(!e||n===e.id)return;let d=[...e.callers??[],...e.callees??[]].find(s=>s.id===n);d&&(this.selectedSymbol.set(d.name),this.fitKey.update(s=>s+1))}toggleFilter(n){this.filters.update(e=>U(A({},e),{[n]:!e[n]})),this.fitKey.update(e=>e+1)}recenter(){this.fitKey.update(n=>n+1)}clearSelection(){this.selectedSymbol.set(null),this.searchInput.set("")}onLayoutChange(n){this.layoutMode.set(n),this.fitKey.update(e=>e+1)}shortPath(n){return H(n)}fileName(n){return n?n.split("/").pop()??"":""}kindLabel(n){return n.charAt(0).toUpperCase()+n.slice(1)}navigateToSpecs(){this.router.navigate(["/specs"])}navigateToDrift(){this.router.navigate(["/drift"])}nodeColor(n){return n==="spec"?"var(--node-spec)":n==="route"?"var(--node-route)":n==="test"?"var(--node-test)":"var(--node-code)"}pickHub(n){this.selectedSymbol.set(n.name),this.fitKey.update(e=>e+1)}detailColor(n){if(n.kind==="spec"){let e=n.linkedSpecs??[],r=e.some(s=>s.state==="broken"||s.state==="orphaned"),d=!r&&e.some(s=>s.state==="drifted");return r?"var(--error)":d?"var(--warn)":"var(--node-spec)"}return n.kind==="test"?"var(--node-test)":n.kind==="route"?"var(--node-route)":"var(--node-code)"}static \u0275fac=function(e){return new(e||t)};static \u0275cmp=q({type:t,selectors:[["app-graph"]],decls:2,vars:1,consts:[["surface","The graph"],[1,"gp-root"],[1,"gp-main"],[1,"gp-toolbar"],["size","sm",3,"change","options","value"],[1,"gp-divider"],["type","button",1,"gp-chip",3,"is-active","--chip-color"],[1,"gp-spacer"],[1,"gp-search"],[1,"gp-search-inner"],["name","search",1,"gp-search-icon",3,"size"],["type","text","placeholder","Fuzzy symbol search\u2026","aria-label","Symbol search",3,"input","value"],["aria-hidden","true",1,"gp-spinner"],["role","listbox",1,"gp-results"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","recenter",3,"size"],[1,"gp-canvas-wrap"],[1,"gp-empty"],[1,"gp-panel"],["type","button",1,"gp-chip",3,"click"],[1,"gp-chip-dot"],[1,"gp-chip-count"],["type","button",1,"gp-result"],["type","button",1,"gp-result",3,"click"],[1,"gp-result-dot"],[1,"gp-result-name","mono"],[1,"gp-result-kind"],[1,"gp-result-path","mono"],[1,"gp-stats"],[3,"nodeClick","nodes","edges","selectedId","fitKey","hiddenIds"],[1,"gp-legend"],[1,"gp-legend-kinds"],[1,"gp-legend-item"],[1,"gp-legend-sep"],[1,"gp-legend-edges"],[1,"gp-legend-edge-row"],["width","16","height","8"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--node-spec)","stroke-width","1.6"],[1,"secondary"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--node-test)","stroke-width","1.6"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--text-muted)","stroke-width","1.6"],["x1","0","y1","4","x2","16","y2","4","stroke","var(--text-muted)","stroke-width","1.6","stroke-dasharray","4 3"],[1,"gp-legend-dot"],[1,"secondary",2,"text-transform","capitalize"],[1,"gp-panel-header"],[1,"gp-panel-header-inner"],[1,"gp-node-dot"],[1,"grow",2,"min-width","0"],[1,"mono","gp-panel-name"],[1,"row","gap-6",2,"margin-top","3px"],[1,"pill"],["type","button","aria-label","Close panel",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"gp-panel-path","row","gap-6"],["name","folder",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","secondary","gp-path-text"],[3,"text"],[1,"gp-panel-body","scroll-y"],[1,"gp-section"],[1,"gp-panel-footer"],[1,"eyebrow","gp-eyebrow"],[1,"gp-code","mono"],[1,"secondary",2,"font-size","12px","line-height","1.6","margin","0"],[1,"muted",2,"font-weight","400","margin-left","5px"],[1,"gp-link-row"],[3,"state"],[1,"mono","grow","gp-link-text"],[1,"muted",2,"font-size","10px","flex-shrink","0","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","max-width","120px"],[1,"muted",2,"font-size","12px","padding","4px 8px"],["type","button",1,"gp-node-link"],["type","button",1,"gp-node-link",3,"click"],["name","box",2,"color","var(--node-code)","flex-shrink","0",3,"size"],[1,"mono","muted","gp-link-file"],["type","button",1,"btn","btn-primary","btn-sm","grow",2,"justify-content","center"],["name","play",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","reveal",3,"size"],[1,"gp-panel-header","gp-overview-head"],["name","graph",2,"color","var(--accent)",3,"size"],[2,"font-weight","600","font-size","13.5px"],[1,"grow"],[1,"mono","muted",2,"font-size","11px"],[1,"secondary",2,"font-size","12px","line-height","1.55","margin","0 0 18px"],[1,"gp-section-plain"],[1,"gp-kind-row"],[1,"row","gap-6",2,"flex-wrap","wrap","align-items","center"],[1,"gp-kind-dot"],[1,"grow",2,"font-size","12.5px","text-transform","capitalize"],[1,"mono","tabular",2,"font-size","12.5px","font-weight","600"],["state","verified"],["aria-hidden","true",1,"gp-skel","gp-skel-sm"],["state","drifted"],["state","broken"],[1,"mono","tabular","muted",2,"font-size","11px","align-self","center"],[1,"gp-edge-row"],["width","20","height","8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--text-muted)","stroke-width","1.8"],["aria-hidden","true",1,"gp-skel","gp-skel-lg"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--node-spec)","stroke-width","1.8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--node-test)","stroke-width","1.8"],["x1","0","y1","4","x2","20","y2","4","stroke","var(--text-muted)","stroke-width","1.8","stroke-dasharray","4 3"],[1,"grow","secondary",2,"font-size","12px"],[1,"mono","tabular","muted",2,"font-size","11px"],["aria-hidden","true",1,"gp-hub-row"],[1,"gp-hub-dot","gp-skel-dot"],["aria-hidden","true",1,"gp-skel","gp-skel-hub"],["type","button",1,"gp-hub-row"],["type","button",1,"gp-hub-row",3,"click"],[1,"gp-hub-dot"],[1,"mono","grow","gp-hub-name"],[1,"muted","gp-hub-degree"],["name","chevron-right",2,"color","var(--text-muted)","flex-shrink","0",3,"size"]],template:function(e,r){e&1&&g(0,se,1,0,"app-pick-project-empty",0)(1,We,26,9,"div",1),e&2&&u(r.status.state().noProject?0:1)},dependencies:[ne,ie,ee,te,ae,oe],styles:["[_nghost-%COMP%]{display:contents}.gp-root[_ngcontent-%COMP%]{flex:1;display:flex;min-height:0;min-width:0}.gp-main[_ngcontent-%COMP%]{flex:1;min-width:0;display:flex;flex-direction:column}.gp-toolbar[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;padding:9px 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel-2, var(--bg-panel));flex-wrap:wrap;flex-shrink:0}.gp-divider[_ngcontent-%COMP%]{width:1px;height:20px;background:var(--border-subtle);flex-shrink:0}.gp-chip[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;height:26px;padding:0 10px;border-radius:999px;font-size:11.5px;font-weight:500;cursor:pointer;border:1px solid var(--border-subtle);background:var(--bg-panel);color:var(--text-secondary);transition:all .1s}.gp-chip.is-active[_ngcontent-%COMP%]{border-color:transparent;background:color-mix(in srgb,var(--chip-color, var(--accent)) 22%,var(--bg-panel));color:var(--chip-color, var(--accent))}.gp-chip-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%}.gp-chip-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code)}.gp-chip-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-chip-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route)}.gp-chip-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test)}.gp-chip-count[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted);font-variant-numeric:tabular-nums}.gp-spacer[_ngcontent-%COMP%]{flex:1}.gp-search[_ngcontent-%COMP%]{position:relative;flex-shrink:0}.gp-search-inner[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;height:28px;padding:0 10px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;width:220px}.gp-search-inner[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{flex:1;background:transparent;border:none;outline:none;color:var(--text-primary);font-size:12px;font-family:var(--font-mono)}.gp-search-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.gp-spinner[_ngcontent-%COMP%]{width:12px;height:12px;border:2px solid var(--border-subtle);border-top-color:var(--accent);border-radius:50%;animation:_ngcontent-%COMP%_gp-spin .7s linear infinite;flex-shrink:0}@keyframes _ngcontent-%COMP%_gp-spin{to{transform:rotate(360deg)}}.gp-results[_ngcontent-%COMP%]{position:absolute;top:32px;left:0;right:0;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:8px;box-shadow:var(--shadow-pop, 0 12px 28px rgba(0, 0, 0, .5));padding:5px;z-index:30;max-height:320px;overflow-y:auto}.gp-result[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border-radius:5px;background:transparent;border:none;cursor:pointer;font:inherit;color:var(--text-primary);text-align:left}.gp-result[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-result-dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%;background:var(--node-code);flex-shrink:0}.gp-result-dot.is-spec[_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-result-dot.is-route[_ngcontent-%COMP%]{background:var(--node-route)}.gp-result-dot.is-test[_ngcontent-%COMP%]{background:var(--node-test)}.gp-result-name[_ngcontent-%COMP%]{font-size:12px;flex-shrink:0}.gp-result-kind[_ngcontent-%COMP%]{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}.gp-result-path[_ngcontent-%COMP%]{flex:1;text-align:right;font-size:10px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-canvas-wrap[_ngcontent-%COMP%]{flex:1;min-height:0;position:relative;display:flex}.gp-canvas-wrap[_ngcontent-%COMP%] app-graph-canvas[_ngcontent-%COMP%]{flex:1;min-height:0}.gp-empty[_ngcontent-%COMP%]{flex:1;display:grid;place-items:center;text-align:center;padding:60px 24px;background:var(--bg-canvas-2, var(--bg-canvas))}.gp-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{font-size:18px;font-weight:600;margin:0 0 8px}.gp-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{color:var(--text-secondary);font-size:13.5px;line-height:1.6;margin:0;max-width:520px}.gp-stats[_ngcontent-%COMP%]{margin-top:18px!important;font-family:var(--font-mono);font-size:11.5px!important;color:var(--text-muted)!important}.gp-legend[_ngcontent-%COMP%]{position:absolute;top:14px;left:14px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;max-width:70%;background:color-mix(in srgb,var(--bg-panel) 86%,transparent);border:1px solid var(--border-subtle);border-radius:8px;padding:6px 10px;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);font-size:11px;pointer-events:none;z-index:3}.gp-legend-kinds[_ngcontent-%COMP%]{display:flex;align-items:center;gap:12px}.gp-legend-item[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px}.gp-legend-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.gp-legend-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code)}.gp-legend-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px}.gp-legend-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route)}.gp-legend-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test)}.gp-legend-sep[_ngcontent-%COMP%]{width:1px;height:16px;background:var(--border-subtle);flex-shrink:0}.gp-legend-edges[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px}.gp-legend-edge-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px}.gp-panel[_ngcontent-%COMP%]{width:360px;flex-shrink:0;border-left:1px solid var(--border-subtle);background:var(--bg-panel);display:flex;flex-direction:column;overflow:hidden}.gp-panel-header[_ngcontent-%COMP%]{padding:12px 14px;border-bottom:1px solid var(--border-subtle);flex-shrink:0}.gp-panel-header-inner[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:8px}.gp-overview-head[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px}.gp-node-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}.gp-node-dot.is-rect[_ngcontent-%COMP%]{border-radius:2px}.gp-panel-name[_ngcontent-%COMP%]{font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-panel-path[_ngcontent-%COMP%]{margin-top:8px;font-size:11.5px;color:var(--text-secondary)}.gp-path-text[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.gp-panel-body[_ngcontent-%COMP%]{flex:1;padding:14px;overflow-y:auto;display:flex;flex-direction:column;gap:18px}.gp-section[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:4px}.gp-section-plain[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:2px}.gp-eyebrow[_ngcontent-%COMP%]{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);margin-bottom:6px}.gp-code[_ngcontent-%COMP%]{margin:0;font-size:11.5px;line-height:1.6;color:var(--text-secondary);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word}.gp-link-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;border:1px solid var(--border-subtle);margin-bottom:5px;font-size:11.5px}.gp-link-text[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}.gp-node-link[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:5px 8px;border-radius:6px;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;text-align:left;font-size:12px}.gp-node-link[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-link-file[_ngcontent-%COMP%]{font-size:10px;flex-shrink:0}.gp-edge-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:4px 0}.gp-kind-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:5px 0}.gp-kind-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%;flex-shrink:0}.gp-kind-dot[data-kind=code][_ngcontent-%COMP%]{background:var(--node-code);box-shadow:0 0 6px var(--node-code)}.gp-kind-dot[data-kind=spec][_ngcontent-%COMP%]{background:var(--node-spec);border-radius:2px;box-shadow:0 0 6px var(--node-spec)}.gp-kind-dot[data-kind=route][_ngcontent-%COMP%]{background:var(--node-route);box-shadow:0 0 6px var(--node-route)}.gp-kind-dot[data-kind=test][_ngcontent-%COMP%]{background:var(--node-test);box-shadow:0 0 6px var(--node-test)}.gp-panel-footer[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:12px 14px;border-top:1px solid var(--border-subtle);flex-shrink:0}.gp-hub-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;width:100%;padding:5px 8px;border-radius:6px;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;text-align:left}.gp-hub-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.gp-hub-dot[_ngcontent-%COMP%]{width:8px;height:8px;flex-shrink:0}.gp-hub-name[_ngcontent-%COMP%]{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gp-hub-degree[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted);flex-shrink:0;font-variant-numeric:tabular-nums}@keyframes _ngcontent-%COMP%_gp-skel-pulse{0%,to{opacity:.35}50%{opacity:.7}}.gp-skel[_ngcontent-%COMP%]{display:inline-block;background:var(--border-subtle);border-radius:4px;animation:_ngcontent-%COMP%_gp-skel-pulse 1.4s ease-in-out infinite}.gp-skel-sm[_ngcontent-%COMP%]{width:24px;height:12px}.gp-skel-lg[_ngcontent-%COMP%]{width:80px;height:12px;flex:1}.gp-skel-hub[_ngcontent-%COMP%]{width:120px;height:12px;flex:1}.gp-skel-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--border-subtle);animation:_ngcontent-%COMP%_gp-skel-pulse 1.4s ease-in-out infinite}.grow[_ngcontent-%COMP%]{flex:1}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}"],changeDetection:0})};function le(t,n,e){return{id:t.id,label:t.name,sub:H(t.filePath),kind:t.kind,x:n,y:e}}function H(t){return t?t.split("/").slice(-2).join("/"):""}function F(t){return t==="spec"?"spec":t==="route"?"route":t==="test"?"test":"code"}export{re as Graph};
@@ -1 +1 @@
1
- import{a as q}from"./chunk-EMGMOEVR.js";import{a as Q}from"./chunk-X2HTISHL.js";import{a as N}from"./chunk-UYC52MBC.js";import{a as R}from"./chunk-WDU3WICG.js";import{a as $,b as j}from"./chunk-HZA6NEAB.js";import{c as V}from"./chunk-GR72OOCN.js";import{c as M}from"./chunk-SHPTC4RL.js";import{a as L}from"./chunk-7RNS77UP.js";import{a as O}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-PDN6QYGJ.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
1
+ import{a as q}from"./chunk-EMGMOEVR.js";import{a as Q}from"./chunk-X2HTISHL.js";import{a as N}from"./chunk-UYC52MBC.js";import{a as $,b as j}from"./chunk-HZA6NEAB.js";import{a as R}from"./chunk-WDU3WICG.js";import{c as M}from"./chunk-SHPTC4RL.js";import{c as V}from"./chunk-GR72OOCN.js";import{a as L}from"./chunk-7RNS77UP.js";import{a as O}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-PDN6QYGJ.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
@@ -0,0 +1,6 @@
1
+ import{a as j}from"./chunk-G7VZT5KB.js";import{a as ie}from"./chunk-EMGMOEVR.js";import{a as oe}from"./chunk-X2HTISHL.js";import{a as ne}from"./chunk-R5W2MDZN.js";import{a as q,b as te}from"./chunk-HZA6NEAB.js";import{a as ee}from"./chunk-WDU3WICG.js";import{c as X}from"./chunk-SHPTC4RL.js";import{a as Z,c as N}from"./chunk-GR72OOCN.js";import{a as Y}from"./chunk-7RNS77UP.js";import{a as J}from"./chunk-E44X4RH2.js";import{Aa as s,Ga as M,I as y,Ia as v,Ka as c,M as C,N as b,Oa as B,Pa as U,Qa as K,R as Q,T as P,Ta as V,Ua as $,Va as l,W as x,Wa as m,Xa as h,aa as z,ea as o,ka as k,lb as f,ra as g,sa as u,va as D,wa as I,xa as p,ya as a,yb as L,za as r,zb as E}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var A=null,ue="self.onmessage = () => {};";function re(){return A||(typeof window<"u"&&!window.MonacoEnvironment&&(window.MonacoEnvironment={getWorker:(n,t)=>{let e=new Blob([ue],{type:"text/javascript"}),i=URL.createObjectURL(e);return new Worker(i,{name:t||"monaco-noop"})}}),A=import("./chunk-FMV5PXRC.js"),A)}var ae=!1;function de(n){ae||(ae=!0,_e(n))}function le(n,t){let e=[],i=t.getValue().split(`
2
+ `),d=null,_=new Map,O=/<!--\s*id\s*:\s*([^\s-][^\s]*)\s*-->/,ge=/^#{1,6}\s+/;for(let S=0;S<i.length;S++){let T=i[S]??"",R=S+1,H=T.match(O);if(H&&H[1]){d!==null&&e.push({severity:n.MarkerSeverity.Warning,message:`Stranded <!-- id: ${d.id} -->: no heading follows on line ${d.line+1}.`,startLineNumber:d.line+1,startColumn:1,endLineNumber:d.line+1,endColumn:(i[d.line]??"").length+1,code:"spec_stranded_id"});let w=H[1];d={id:w,line:S};let G=_.get(w);G!==void 0?e.push({severity:n.MarkerSeverity.Warning,message:`Duplicate spec ID "${w}" \u2014 first seen on line ${G+1}. The second occurrence will be silently lost by the parser.`,startLineNumber:R,startColumn:T.indexOf(w)+1,endLineNumber:R,endColumn:T.indexOf(w)+w.length+1,code:"spec_duplicate_id"}):_.set(w,S);continue}ge.test(T)&&(d===null?e.push({severity:n.MarkerSeverity.Error,message:"This heading has no embedded ID. Add `<!-- id: REQ-X -->` on the line above it \u2014 required by the SpecShip parser.",startLineNumber:R,startColumn:1,endLineNumber:R,endColumn:T.length+1,code:"spec_missing_id"}):d=null)}n.editor.setModelMarkers(t,"specship-spec",e)}function _e(n){n.languages.registerCompletionItemProvider("markdown",{provideCompletionItems:(t,e)=>{let i=t.getWordUntilPosition(e),d={startLineNumber:e.lineNumber,endLineNumber:e.lineNumber,startColumn:i.startColumn,endColumn:i.endColumn},_=n.languages.CompletionItemKind,O=n.languages.CompletionItemInsertTextRule;return{suggestions:[{label:"req",kind:_.Snippet,insertText:["<!-- id: REQ-${1:AREA}-${2:001} -->","## ${3:Title MUST be concrete}","","${4:Body \u2014 describe the contract, not the implementation.}","","## Acceptance","<!-- id: REQ-${1:AREA}-${2:001}.A1 -->","- ${5:First testable acceptance criterion}","$0"].join(`
3
+ `),insertTextRules:O.InsertAsSnippet,documentation:"Insert a full requirement (heading + acceptance) with embedded IDs.",detail:"SpecShip \xB7 requirement",range:d},{label:"doc",kind:_.Snippet,insertText:["---","id: ${1:AREA}-DOC","title: ${2:Title}","owner: ${3:team-or-person}","priority: ${4|high,medium,low|}","---","","<!-- id: ${1:AREA}-DOC -->","# ${2:Title}","","${5:One-paragraph summary of what this document covers.}","$0"].join(`
4
+ `),insertTextRules:O.InsertAsSnippet,documentation:"Insert a new spec document with frontmatter.",detail:"SpecShip \xB7 document",range:d},{label:"accept",kind:_.Snippet,insertText:["## Acceptance","<!-- id: ${1:REQ-X}.A1 -->","- ${2:First testable acceptance criterion}","<!-- id: ${1:REQ-X}.A2 -->","- ${3:Second testable acceptance criterion}","$0"].join(`
5
+ `),insertTextRules:O.InsertAsSnippet,documentation:"Insert an Acceptance section with two ID-d bullets.",detail:"SpecShip \xB7 acceptance",range:d},{label:"impl",kind:_.Snippet,insertText:["implementations:"," - ${1:src/path/to/file.ts}:${2:QualifiedSymbol}","$0"].join(`
6
+ `),insertTextRules:O.InsertAsSnippet,documentation:"Insert an implementations block linking the spec to code.",detail:"SpecShip \xB7 implementations",range:d}]}},triggerCharacters:["r","d","a","i"]})}var xe=["host"];function ve(n,t){if(n&1&&(a(0,"span",5),l(1),r()),n&2){let e=c();p("title",e.path),o(),m(e.path)}}function fe(n,t){n&1&&(a(0,"div",15),l(1,"Loading editor\u2026"),r())}var F=class n{sanitizer=y(L);destroyRef=y(Q);value="";path="";valueChange=new P;validationChange=new P;save=new P;cancel=new P;hostRef;loading=x(!0);currentValue=x("");errorCount=x(0);warningCount=x(0);dirty=x(!1);previewHtml=f(()=>this.sanitizer.bypassSecurityTrustHtml(j(this.currentValue()||"")));tokenCount=f(()=>Math.max(1,Math.round((this.currentValue()||"").length/4)));statusLabel=f(()=>{let t=this.errorCount(),e=this.warningCount();return t>0?`${t} error${t===1?"":"s"}`:e>0?`${e} warning${e===1?"":"s"}`:"clean"});statusKind=f(()=>this.errorCount()>0?"error":this.warningCount()>0?"warn":"ok");monaco=null;editor=null;model=null;diagnosticsTimer=null;async ngAfterViewInit(){this.currentValue.set(this.value);try{let t=await re();this.monaco=t,de(t),this.model=t.editor.createModel(this.value,"markdown"),this.editor=t.editor.create(this.hostRef.nativeElement,{model:this.model,theme:this.preferDark()?"vs-dark":"vs",automaticLayout:!0,wordWrap:"on",minimap:{enabled:!1},scrollBeyondLastLine:!1,renderWhitespace:"none",fontSize:13,lineNumbers:"on",folding:!1,tabSize:2,insertSpaces:!0,contextmenu:!1}),this.editor.onDidChangeModelContent(()=>this.handleEdit()),this.runDiagnosticsNow(),this.loading.set(!1)}catch(t){console.error("[spec-editor] failed to load Monaco",t),this.loading.set(!1)}this.destroyRef.onDestroy(()=>this.dispose())}ngOnDestroy(){this.dispose()}onSave(){this.save.emit()}onCancel(){this.cancel.emit()}handleEdit(){if(!this.model)return;let t=this.model.getValue();this.currentValue.set(t),this.dirty.set(t!==this.value),this.valueChange.emit(t),this.diagnosticsTimer!==null&&clearTimeout(this.diagnosticsTimer),this.diagnosticsTimer=setTimeout(()=>this.runDiagnosticsNow(),500)}runDiagnosticsNow(){if(!this.monaco||!this.model)return;le(this.monaco,this.model);let t=this.monaco.editor.getModelMarkers({resource:this.model.uri,owner:"specship-spec"}),e=t.filter(d=>d.severity===this.monaco.MarkerSeverity.Error).length,i=t.filter(d=>d.severity===this.monaco.MarkerSeverity.Warning).length;this.errorCount.set(e),this.warningCount.set(i),this.validationChange.emit({errors:e,warnings:i})}preferDark(){if(typeof window>"u")return!1;try{return window.matchMedia("(prefers-color-scheme: dark)").matches}catch{return!1}}dispose(){this.diagnosticsTimer!==null&&(clearTimeout(this.diagnosticsTimer),this.diagnosticsTimer=null),this.editor?.dispose(),this.editor=null,this.model?.dispose(),this.model=null}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=k({type:n,selectors:[["app-spec-editor"]],viewQuery:function(e,i){if(e&1&&B(xe,7),e&2){let d;U(d=K())&&(i.hostRef=d.first)}},inputs:{value:"value",path:"path"},outputs:{valueChange:"valueChange",validationChange:"validationChange",save:"save",cancel:"cancel"},decls:23,vars:16,consts:[["host",""],[1,"editor-shell","col"],[1,"toolbar","row","gap-8"],["name","memory",3,"size"],[1,"title"],[1,"path","mono",3,"title"],[1,"grow"],[1,"status-pill"],[1,"dot"],[1,"tokens","mono","tabular","muted",3,"title"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["type","button",1,"btn","btn-primary","btn-sm",3,"click","disabled","title"],["name","check",3,"size"],[1,"panes","row"],[1,"editor-pane"],[1,"loading"],[1,"monaco-host"],[1,"preview-pane","md-content",3,"innerHTML"]],template:function(e,i){e&1&&(a(0,"div",1)(1,"div",2),s(2,"app-icon",3),a(3,"span",4),l(4,"Spec editor"),r(),g(5,ve,2,2,"span",5),s(6,"span",6),a(7,"span",7),s(8,"span",8),l(9),r(),a(10,"span",9),l(11),r(),a(12,"button",10),v("click",function(){return i.onCancel()}),l(13," Cancel "),r(),a(14,"button",11),v("click",function(){return i.onSave()}),s(15,"app-icon",12),l(16," Save "),r()(),a(17,"div",13)(18,"div",14),g(19,fe,2,0,"div",15),s(20,"div",16,0),r(),s(22,"div",17),r()()),e&2&&(o(2),p("size",14),o(3),u(i.path?5:-1),o(2),$("ok",i.statusKind()==="ok")("warn",i.statusKind()==="warn")("error",i.statusKind()==="error"),o(2),h(" ",i.statusLabel()," "),o(),p("title","~"+i.tokenCount()+" tokens (rough estimate)"),o(),h(" ~",i.tokenCount(),"t "),o(3),p("disabled",!i.dirty()||i.errorCount()>0)("title",i.errorCount()>0?"Fix errors before saving":i.dirty()?"Save changes":"No changes to save"),o(),p("size",13),o(4),u(i.loading()?19:-1),o(3),p("innerHTML",i.previewHtml(),z))},dependencies:[E],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex:1;min-height:0}.editor-shell[_ngcontent-%COMP%]{flex:1;min-height:0;border:1px solid var(--border-subtle);border-radius:10px;overflow:hidden;background:var(--bg-panel)}.toolbar[_ngcontent-%COMP%]{align-items:center;padding:8px 12px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel);flex-wrap:wrap;row-gap:6px}.toolbar[_ngcontent-%COMP%] .title[_ngcontent-%COMP%]{font-size:12.5px;font-weight:650;color:var(--text-primary)}.toolbar[_ngcontent-%COMP%] .path[_ngcontent-%COMP%]{font-size:11px;color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:320px}.toolbar[_ngcontent-%COMP%] .tokens[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted)}.status-pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;white-space:nowrap}.status-pill[_ngcontent-%COMP%] .dot[_ngcontent-%COMP%]{width:7px;height:7px;border-radius:50%}.status-pill.ok[_ngcontent-%COMP%]{color:var(--success);background:var(--success-soft)}.status-pill.ok[_ngcontent-%COMP%] .dot[_ngcontent-%COMP%]{background:var(--success)}.status-pill.warn[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.status-pill.warn[_ngcontent-%COMP%] .dot[_ngcontent-%COMP%]{background:var(--warn)}.status-pill.error[_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.status-pill.error[_ngcontent-%COMP%] .dot[_ngcontent-%COMP%]{background:var(--error)}.panes[_ngcontent-%COMP%]{flex:1;min-height:0}.editor-pane[_ngcontent-%COMP%]{flex:1;min-width:0;min-height:0;position:relative;border-right:1px solid var(--border-subtle)}.loading[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--text-muted);font-size:12px;background:var(--bg-canvas);z-index:1}.monaco-host[_ngcontent-%COMP%]{position:absolute;inset:0}.preview-pane[_ngcontent-%COMP%]{flex:1;min-width:0;min-height:0;padding:14px 18px;overflow:auto;background:var(--bg-canvas)}.preview-pane.md-content[_ngcontent-%COMP%] .md-h1[_ngcontent-%COMP%]{font-size:15px;font-weight:650;color:var(--text-primary);letter-spacing:-.01em;margin:0 0 10px}.preview-pane.md-content[_ngcontent-%COMP%] .md-h2[_ngcontent-%COMP%]{font-size:13px;font-weight:650;color:var(--text-primary);letter-spacing:-.005em;margin:18px 0 6px;padding-bottom:4px;border-bottom:1px solid var(--border-subtle)}.preview-pane.md-content[_ngcontent-%COMP%] .md-h3[_ngcontent-%COMP%]{font-size:12px;font-weight:650;color:var(--text-primary);margin:14px 0 6px}.preview-pane.md-content[_ngcontent-%COMP%] .md-h4[_ngcontent-%COMP%]{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin:12px 0 4px}.preview-pane.md-content[_ngcontent-%COMP%] .md-p[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.6;color:var(--text-secondary);margin:0 0 4px;overflow-wrap:anywhere}.preview-pane.md-content[_ngcontent-%COMP%] .md-p[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-primary)}.preview-pane.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%], .preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%]{padding:0;margin:4px 0 6px}.preview-pane.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{position:relative;padding:2px 0 2px 22px;font-size:12.5px;line-height:1.6;color:var(--text-secondary);overflow-wrap:anywhere}.preview-pane.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-primary)}.preview-pane.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%]{list-style:none}.preview-pane.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:before{content:"\\2022";position:absolute;left:6px;top:2px;color:var(--text-faint)}.preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%]{list-style:none;counter-reset:md-ol}.preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{counter-increment:md-ol}.preview-pane.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:before{content:counter(md-ol) ".";position:absolute;left:0;top:2px;color:var(--text-faint);font-family:var(--font-mono);font-size:11.5px;min-width:18px;text-align:right}.preview-pane.md-content[_ngcontent-%COMP%] .md-spacer[_ngcontent-%COMP%]{height:6px}.preview-pane.md-content[_ngcontent-%COMP%] .md-import[_ngcontent-%COMP%]{display:inline-block;font-size:11.5px;color:var(--node-route);background:var(--node-route-soft);padding:2px 8px;border-radius:5px;margin:4px 0}.preview-pane.md-content[_ngcontent-%COMP%] .md-inline-code[_ngcontent-%COMP%]{font-size:11.5px;background:var(--bg-canvas);padding:1px 6px;border-radius:4px;border:1px solid var(--border-subtle);color:var(--node-spec)}.preview-pane.md-content[_ngcontent-%COMP%] .md-blockquote[_ngcontent-%COMP%]{margin:6px 0;padding:8px 12px;border-left:3px solid var(--accent);background:var(--accent-soft);color:var(--text-secondary);font-size:12.5px;line-height:1.55;border-radius:0 6px 6px 0}.preview-pane.md-content[_ngcontent-%COMP%] .md-pre[_ngcontent-%COMP%]{position:relative;margin:8px 0 10px;padding:12px 14px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;overflow-x:auto}.preview-pane.md-content[_ngcontent-%COMP%] .md-pre[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{display:block;font-size:11.5px;line-height:1.55;color:var(--text-primary);white-space:pre}.preview-pane.md-content[_ngcontent-%COMP%] .md-pre-lang[_ngcontent-%COMP%]{position:absolute;top:6px;right:10px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:lowercase;background:var(--bg-canvas);padding:1px 6px;border-radius:4px;border:1px solid var(--border-subtle)}.preview-pane.md-content[_ngcontent-%COMP%] .md-table-scroll[_ngcontent-%COMP%]{overflow-x:auto;margin:10px 0;border:1px solid var(--border-subtle);border-radius:8px}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%]{width:100%;border-collapse:collapse;font-size:11.5px}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], .preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{padding:8px 12px;text-align:left;vertical-align:top;border-bottom:1px solid var(--border-subtle)}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th[_ngcontent-%COMP%]{background:var(--bg-panel);font-weight:650;color:var(--text-primary);font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;border-bottom:1px solid var(--border-strong);white-space:nowrap}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{color:var(--text-secondary)}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%]{border-bottom:0}.preview-pane.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.preview-pane.md-content[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:first-child{margin-top:0}'],changeDetection:0})};function Ce(n,t){n&1&&(a(0,"div",14),l(1),r()),n&2&&(o(),m(t))}function be(n,t){if(n&1){let e=M();a(0,"div",0),v("click",function(){C(e);let d=c();return b(d.onBackdropClick())}),r(),a(1,"div",1)(2,"header",2)(3,"div",3)(4,"div",4),l(5,"Draft a new spec with Claude"),r(),a(6,"div",5),l(7,"Describe the feature in one sentence. Claude takes it from there."),r()(),a(8,"button",6),v("click",function(){C(e);let d=c();return b(d.onCloseClick())}),s(9,"app-icon",7),r()(),a(10,"div",8)(11,"label",9),l(12,"Feature description"),r(),a(13,"textarea",10),v("input",function(d){C(e);let _=c();return b(_.onDescriptionInput(d))}),r(),a(14,"div",11),l(15,"This will run in Claude Code:"),r(),a(16,"pre",12),l(17),r()(),a(18,"footer",13),g(19,Ce,2,1,"div",14),s(20,"span",15),a(21,"button",16),v("click",function(){C(e);let d=c();return b(d.onCopyToClipboard())}),s(22,"app-icon",17),l(23," Copy prompt "),r(),a(24,"button",18),v("click",function(){C(e);let d=c();return b(d.onOpenInClaude())}),s(25,"app-icon",19),l(26," Open in Claude Code "),r()()()}if(n&2){let e,i=c();o(9),p("size",16),o(4),p("value",i.description()),o(4),m(i.slashCommand()),o(2),u((e=i.toast())?19:-1,e),o(2),p("disabled",!i.canSubmit()),o(),p("size",13),o(2),p("disabled",!i.canSubmit()),o(),p("size",13)}}var W=class n{open=!1;close=new P;description=x("");toast=x(null);slashCommand=f(()=>{let t=this.description().trim();return t?`/ss-spec-author "${t.replace(/"/g,'\\"')}"`:"/ss-spec-author"});canSubmit=f(()=>this.description().trim().length>0);onDescriptionInput(t){let e=t.target;this.description.set(e.value)}onBackdropClick(){this.dismiss()}onCloseClick(){this.dismiss()}async onOpenInClaude(){if(!this.canSubmit())return;let t=this.slashCommand();await this.writeToClipboard(t);try{window.location.href=`claude://prompt?text=${encodeURIComponent(t)}`,this.flashToast("Opening Claude Code\u2026 (also copied to clipboard)")}catch{this.flashToast("Claude Code handler unavailable \u2014 prompt copied to clipboard.")}}async onCopyToClipboard(){if(!this.canSubmit())return;let t=this.slashCommand(),e=await this.writeToClipboard(t);this.flashToast(e?"Copied! Switch to Claude Code and paste.":"Could not access clipboard \u2014 copy the prompt manually.")}async writeToClipboard(t){if(!navigator.clipboard)return!1;try{return await navigator.clipboard.writeText(t),!0}catch{return!1}}flashToast(t){this.toast.set(t),setTimeout(()=>this.toast.set(null),2500)}dismiss(){this.description.set(""),this.toast.set(null),this.close.emit()}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=k({type:n,selectors:[["app-draft-with-claude-modal"]],inputs:{open:"open"},outputs:{close:"close"},decls:1,vars:1,consts:[["role","presentation",1,"backdrop",3,"click"],["role","dialog","aria-labelledby","draft-modal-title","aria-modal","true",1,"modal"],[1,"head"],[1,"title-block"],["id","draft-modal-title",1,"title"],[1,"sub"],["type","button","aria-label","Close",1,"close",3,"click"],["name","x",3,"size"],[1,"body"],["for","draft-description",1,"field-label"],["id","draft-description","rows","3","placeholder","e.g. Failed payment retries should back off with T+1d, T+3d, T+7d then downgrade the account.","autofocus","",1,"field",3,"input","value"],[1,"preview-label"],[1,"preview","mono"],[1,"foot"],[1,"toast"],[1,"grow"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click","disabled"],["name","copy",3,"size"],["type","button",1,"btn","btn-primary","btn-sm",3,"click","disabled"],["name","external",3,"size"]],template:function(e,i){e&1&&g(0,be,27,8),e&2&&u(i.open?0:-1)},dependencies:[E],styles:[".backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;z-index:100;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal[_ngcontent-%COMP%]{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:min(560px,100vw - 32px);max-height:calc(100vh - 64px);background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:12px;box-shadow:0 24px 48px #0006;z-index:101;display:flex;flex-direction:column;overflow:hidden}.head[_ngcontent-%COMP%]{display:flex;align-items:flex-start;gap:12px;padding:16px 18px;border-bottom:1px solid var(--border-subtle)}.head[_ngcontent-%COMP%] .title-block[_ngcontent-%COMP%]{flex:1;min-width:0}.head[_ngcontent-%COMP%] .title[_ngcontent-%COMP%]{font-size:14.5px;font-weight:650;color:var(--text-primary);letter-spacing:-.01em}.head[_ngcontent-%COMP%] .sub[_ngcontent-%COMP%]{font-size:12px;color:var(--text-secondary);margin-top:2px;line-height:1.45}.head[_ngcontent-%COMP%] .close[_ngcontent-%COMP%]{appearance:none;background:transparent;border:0;width:28px;height:28px;border-radius:6px;color:var(--text-muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s,color .12s}.head[_ngcontent-%COMP%] .close[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.head[_ngcontent-%COMP%] .close[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.body[_ngcontent-%COMP%]{padding:16px 18px;display:flex;flex-direction:column;gap:10px;overflow-y:auto}.field-label[_ngcontent-%COMP%]{font-size:11px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em}.field[_ngcontent-%COMP%]{width:100%;box-sizing:border-box;padding:10px 12px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:8px;color:var(--text-primary);font-family:var(--font-ui);font-size:13px;line-height:1.5;resize:vertical}.field[_ngcontent-%COMP%]:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}.preview-label[_ngcontent-%COMP%]{font-size:11px;color:var(--text-muted);margin-top:4px}.preview[_ngcontent-%COMP%]{margin:0;padding:10px 12px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:8px;font-size:11.5px;line-height:1.5;color:var(--node-spec);font-family:var(--font-mono);white-space:pre-wrap;word-break:break-all}.foot[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:12px 18px;border-top:1px solid var(--border-subtle);background:var(--bg-canvas);flex-wrap:wrap}.foot[_ngcontent-%COMP%] .grow[_ngcontent-%COMP%]{flex:1}.toast[_ngcontent-%COMP%]{font-size:11.5px;color:var(--success);background:var(--success-soft);padding:4px 10px;border-radius:999px;white-space:nowrap}"],changeDetection:0})};var he=(n,t)=>t.path,me=(n,t)=>t.id,ye=(n,t)=>t.briefId;function Me(n,t){n&1&&s(0,"app-pick-project-empty",0)}function we(n,t){if(n&1&&(s(0,"span",6),a(1,"span",17),l(2),r()),n&2){let e=c();o(2),h("",e.summary.conflicts," \u26A0")}}function Pe(n,t){if(n&1&&(a(0,"div",8)(1,"span")(2,"b",15),l(3),r(),l(4," ideas"),r(),a(5,"span",16),l(6,"\u2192"),r(),a(7,"span")(8,"b",15),l(9),r(),l(10," specs"),r(),a(11,"span",16),l(12,"\u2192"),r(),a(13,"span")(14,"b",15),l(15),r(),l(16," impl \xB7 "),a(17,"b",15),l(18),r(),l(19," ver"),r(),g(20,we,3,1),r()),n&2){let e=t;o(3),m(e.summary.ideas),o(6),m(e.summary.specified),o(6),m(e.summary.links.implemented),o(3),m(e.summary.links.verified),o(2),u(e.summary.conflicts>0?20:-1)}}function Oe(n,t){n&1&&s(0,"app-empty",10)}function Se(n,t){if(n&1&&(a(0,"span",22),l(1),r()),n&2){let e=c().$implicit,i=c(2);o(),h(" ",i.driftCountForGroup(e)," ")}}function ke(n,t){if(n&1){let e=M();a(0,"div",25),v("click",function(){let d=C(e).$implicit,_=c(4);return b(_.select(d.id))}),s(1,"span",26),a(2,"div",27)(3,"div",28),l(4),r(),a(5,"div",29),l(6),r()()()}if(n&2){let e=t.$implicit,i=c(4);$("selected",i.sel()===e.id),o(),V("background",i.stateColorFor(e.kind)),o(2),V("color",i.sel()===e.id?"var(--accent)":"var(--text-primary)"),o(),m(e.id),o(2),m(e.title)}}function Ee(n,t){if(n&1&&(a(0,"div",23),D(1,ke,7,8,"div",24,me),r()),n&2){let e=c().$implicit;o(),I(e.specs)}}function Te(n,t){if(n&1){let e=M();a(0,"div",18),v("click",function(){let d=C(e).$implicit,_=c(2);return b(_.toggleGroup(d.path))}),s(1,"app-icon",19)(2,"app-icon",20),a(3,"span",21),l(4),r(),g(5,Se,2,1,"span",22),r(),g(6,Ee,3,0,"div",23)}if(n&2){let e=t.$implicit,i=c(2);o(),p("name",i.isGroupOpen(e.path)?"chevronDown":"chevronRight")("size",12),o(),p("size",13),o(2),m(e.title),o(),u(i.driftCountForGroup(e)>0?5:-1),o(),u(i.isGroupOpen(e.path)?6:-1)}}function ze(n,t){if(n&1){let e=M();a(0,"div",25),v("click",function(){let d=C(e).$implicit,_=c(3);return b(_.select(d.briefId))}),s(1,"span",33),a(2,"div",27)(3,"div",29),l(4),r()()()}if(n&2){let e=t.$implicit,i=c(3);$("selected",i.sel()===e.briefId),o(4),m(e.title)}}function De(n,t){if(n&1&&(a(0,"div",30)(1,"span",31),l(2,"IDEAS"),r(),a(3,"span",32),l(4),r()(),D(5,ze,5,3,"div",24,ye)),n&2){let e=c(2);o(4),m(e.ideas().length),o(),I(e.ideas())}}function Ie(n,t){if(n&1&&(a(0,"div",34),l(1),r()),n&2){let e=c();o(),h("Loading source for ",e.id,"\u2026")}}function $e(n,t){if(n&1){let e=M();a(0,"app-spec-editor",38),v("valueChange",function(d){C(e);let _=c(4);return b(_.onEditorValueChange(d))})("save",function(){C(e);let d=c(4);return b(d.onEditorSave())})("cancel",function(){C(e);let d=c(4);return b(d.onEditorCancel())}),r()}if(n&2){let e=c(),i=c(3);p("value",i.editingSource())("path",e.sourcePath)}}function Ne(n,t){n&1&&(a(0,"div",36),l(1),r()),n&2&&(o(),m(t))}function Re(n,t){n&1&&(a(0,"div",37),l(1,"Saving\u2026"),r())}function Ve(n,t){if(n&1&&(g(0,Ie,2,1,"div",34)(1,$e,1,2,"app-spec-editor",35),g(2,Ne,2,1,"div",36),g(3,Re,2,0,"div",37)),n&2){let e,i=c(3);u(i.editingSource()===null?0:1),o(2),u((e=i.saveError())?2:-1,e),o(),u(i.saving()?3:-1)}}function Le(n,t){if(n&1&&g(0,Ve,4,3),n&2){let e,i=c(2);u((e=i.selectedSpec())?0:-1,e)}}function je(n,t){if(n&1&&(a(0,"app-pill"),l(1),r()),n&2){let e=c();o(),m(e.priority)}}function Ae(n,t){if(n&1&&(a(0,"div",45)(1,"div",46),l(2,"Owner"),r(),a(3,"div",47),l(4),r()()),n&2){let e=c();o(4),m(e.owner)}}function Fe(n,t){if(n&1&&(a(0,"details",50)(1,"summary",63),l(2,"Brainstorm"),r(),s(3,"div",64),r()),n&2){let e=c(3);o(3),p("innerHTML",e.briefHtml(),z)}}function We(n,t){n&1&&s(0,"div",51)}function He(n,t){if(n&1&&(a(0,"app-pill",67),l(1),r()),n&2){let e=c().$implicit;o(),h("",e.driftAxis," drift")}}function qe(n,t){if(n&1&&(a(0,"div",66),s(1,"app-state-pill",42),g(2,He,2,1,"app-pill",67),a(3,"span",68),l(4),r(),a(5,"app-pill"),l(6),r(),a(7,"button",69),s(8,"app-icon",60),l(9," Reveal "),r()()),n&2){let e=t.$implicit,i=t.$index;V("border-top",i>0?"1px solid var(--border-subtle)":"none"),o(),p("state",e.state),o(),u(e.driftAxis?2:-1),o(2),m(e.targetQualifiedName),o(2),m(e.provenance),o(2),p("size",12)}}function Ge(n,t){if(n&1&&(a(0,"div",52),D(1,qe,10,7,"div",65,me),r()),n&2){let e=c(3);o(),I(e.selectedLinks())}}function Qe(n,t){n&1&&(a(0,"div",53),s(1,"app-icon",70),a(2,"div",71),l(3," Orphaned \u2014 no code implements this requirement yet "),r()()),n&2&&(o(),p("size",16))}function Be(n,t){n&1&&(a(0,"div",62),l(1),r()),n&2&&(o(),m(t))}function Ue(n,t){if(n&1){let e=M();a(0,"div",12)(1,"div",39)(2,"span",40),l(3),r(),s(4,"app-copy-btn",41)(5,"div",6)(6,"app-state-pill",42),g(7,je,2,1,"app-pill"),r(),a(8,"h1",43),l(9),r(),a(10,"div",44)(11,"div",45)(12,"div",46),l(13,"Kind"),r(),a(14,"div",47),l(15),r()(),g(16,Ae,5,1,"div",45),a(17,"div",45)(18,"div",46),l(19,"Doc"),r(),a(20,"div",47),l(21),r()(),a(22,"div",45)(23,"div",46),l(24,"Siblings"),r(),a(25,"div",47),l(26),r()(),a(27,"div",45)(28,"div",46),l(29,"Links"),r(),a(30,"div",47),l(31),r()()(),a(32,"div",48),l(33,"Requirement"),r(),s(34,"div",49),g(35,Fe,4,1,"details",50),a(36,"div",48),l(37,"Linked code"),r(),g(38,We,1,0,"div",51)(39,Ge,3,0,"div",52)(40,Qe,4,1,"div",53),a(41,"div",54)(42,"button",55),s(43,"app-icon",56),l(44," Implement "),r(),a(45,"button",57),s(46,"app-icon",58),l(47," Verify "),r(),a(48,"button",59),v("click",function(){C(e);let d=c(2);return b(d.onEditClick())}),s(49,"app-icon",60),l(50," Edit spec "),r(),a(51,"button",59),v("click",function(){let d=C(e),_=c(2);return b(_.goToGraph(d.id))}),s(52,"app-icon",61),l(53," Show in graph "),r()(),g(54,Be,2,1,"div",62),r()}if(n&2){let e,i=t,d=c(2);o(3),m(i.id),o(),p("text",i.id),o(2),p("state",i.kind),o(),u(i.priority?7:-1),o(2),m(i.title),o(6),m(i.kind),o(),u(i.owner?16:-1),o(5),m(i.sourcePath.replace("specs/","")),o(5),h("",d.selectedSiblings().length," reqs"),o(5),m(d.selectedLinks().length),o(3),p("innerHTML",d.renderBody(i.body),z),o(),u(d.briefResource.state().data?35:-1),o(3),u(d.detailResource.state().loading?38:d.selectedLinks().length>0?39:40),o(5),p("size",13),o(3),p("size",13),o(3),p("size",13),o(3),p("size",13),o(2),u((e=d.saveError())?54:-1,e)}}function Ke(n,t){n&1&&(a(0,"app-empty",13)(1,"code",72),l(2,"specship init -i"),r()())}function Xe(n,t){if(n&1){let e=M();a(0,"div",1)(1,"div",2)(2,"div",3),s(3,"app-icon",4),a(4,"span",5),l(5,"Specs"),r(),s(6,"span",6),a(7,"span",7),l(8),r()(),g(9,Pe,21,5,"div",8),a(10,"div",9),g(11,Oe,1,0,"app-empty",10),D(12,Te,7,6,null,null,he),g(14,De,7,1),r()(),a(15,"div",11),g(16,Le,1,1)(17,Ue,55,18,"div",12)(18,Ke,3,0,"app-empty",13),r()(),a(19,"app-draft-with-claude-modal",14),v("close",function(){C(e);let d=c();return b(d.onDraftModalClose())}),r()}if(n&2){let e,i,d=c();o(3),p("size",15),o(5),h(" ",d.resource.state().loading?"\u2026":d.totalCount()+" reqs"," "),o(),u((e=d.funnel())?9:-1,e),o(2),u(d.groups().length===0&&!d.resource.state().loading?11:-1),o(),I(d.groups()),o(2),u(d.ideas().length>0?14:-1),o(2),u(d.editing()?16:(i=d.selectedSpec())?17:18,i),o(3),p("open",d.draftModalOpen())}}function Je(n){return n.replace(/<!--[\s\S]*?-->/g,"")}var pe=class n{api=y(J);projects=y(Y);router=y(X);conn=y(Z);sanitizer=y(L);resource=N(this.api,()=>`/api/specs${this.projects.projectQuery()}`);funnelResource=N(this.api,()=>`/api/spec/funnel${this.projects.projectQuery()}`);funnel=f(()=>this.funnelResource.state().data??null);ideas=f(()=>this.funnel()?.ideas??[]);detailResource=N(this.api,()=>{let t=this.sel();return t?`/api/spec/${encodeURIComponent(t)}${this.projects.projectQuery()}`:null});briefResource=N(this.api,()=>{let t=this.sel();return t?`/api/spec/${encodeURIComponent(t)}/brief${this.projects.projectQuery()}`:null});briefHtml=f(()=>this.renderBody(this.briefResource.state().data?.markdown??""));sel=x(null);expandedGroups=x(new Set);editing=x(!1);editingSource=x(null);editingDirty=x(!1);saving=x(!1);saveError=x(null);draftModalOpen=x(!1);STATE=q;groups=f(()=>{let t=(this.resource.state().data?.specs??[]).filter(i=>i.kind!=="brief"),e=new Map;for(let i of t){let d=i.sourcePath||"(unknown)";e.has(d)||e.set(d,{path:d,title:d.replace(/^specs\//,""),specs:[]}),e.get(d).specs.push(i)}return[...e.values()]});totalCount=f(()=>this.groups().reduce((t,e)=>t+e.specs.length,0));selectedSpec=f(()=>{let t=this.sel();return t?(this.resource.state().data?.specs??[]).find(i=>i.id===t)??null:null});selectedLinks=f(()=>this.detailResource.state().data?.links??[]);selectedSiblings=f(()=>{let t=this.selectedSpec();if(!t)return[];let e=this.groups().find(i=>i.path===t.sourcePath);return e?e.specs.filter(i=>i.id!==t.id):[]});isGroupOpen(t){return!this.expandedGroups().has("closed:"+t)}toggleGroup(t){this.expandedGroups.update(e=>{let i="closed:"+t,d=new Set(e);return d.has(i)?d.delete(i):d.add(i),d})}driftCountForGroup(t){let e=this.selectedSpec();return!e||e.sourcePath!==t.path?0:this.selectedLinks().filter(i=>["drifted","broken","orphaned"].includes(i.state)).length}stateColorFor(t){return q[t]?.color??"var(--node-spec)"}select(t){this.editing()&&(this.editing.set(!1),this.editingSource.set(null),this.editingDirty.set(!1)),this.sel.set(t)}renderBody(t){return this.sanitizer.bypassSecurityTrustHtml(j(Je(t)))}goToGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}async onEditClick(){let t=this.selectedSpec();if(t){this.saveError.set(null),this.editing.set(!0),this.editingSource.set(null);try{let e=this.projects.projectQuery(),i=await this.api.get(`/api/spec/${encodeURIComponent(t.id)}${e}`);this.editingSource.set(i.source??t.body)}catch(e){this.saveError.set(`Couldn't load source: ${e instanceof Error?e.message:String(e)}`),this.editing.set(!1)}}}onEditorValueChange(t){this.editingSource.set(t),this.editingDirty.set(!0)}async onEditorSave(){let t=this.selectedSpec(),e=this.editingSource();if(!(!t||e===null)){if(!this.conn.online()){this.saveError.set("Offline \u2014 reconnect to save your changes");return}this.saving.set(!0),this.saveError.set(null);try{let i=this.projects.projectQuery();await this.api.put(`/api/spec/${encodeURIComponent(t.id)}${i}`,{content:e}),this.editing.set(!1),this.editingDirty.set(!1),this.editingSource.set(null),this.resource.refetch()}catch(i){this.saveError.set(`Save failed: ${i instanceof Error?i.message:String(i)}`)}finally{this.saving.set(!1)}}}onEditorCancel(){this.editingDirty()&&!window.confirm("Discard unsaved changes?")||(this.editing.set(!1),this.editingSource.set(null),this.editingDirty.set(!1),this.saveError.set(null))}onDraftWithClaudeClick(){this.draftModalOpen.set(!0)}onDraftModalClose(){this.draftModalOpen.set(!1)}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=k({type:n,selectors:[["app-specs"]],decls:2,vars:1,consts:[["surface","Specs"],[1,"specs-shell"],[1,"tree-col"],[1,"tree-header","row","gap-8"],["name","book",2,"color","var(--accent)",3,"size"],[2,"font-weight","600","font-size","13px"],[1,"grow"],[1,"muted","tabular",2,"font-size","11px"],["aria-label","Spec lifecycle funnel",1,"row","gap-8",2,"padding","6px 12px","border-bottom","1px solid var(--border-subtle)","font-size","11px","color","var(--text-secondary)"],[1,"scroll-y","tree-scroll"],["icon","book","title","No specs found","body","Run specship init -i against a project with a specs/ directory."],[1,"detail-col","col"],[1,"scroll-y","detail-scroll"],["icon","book","title","Pick a spec from the tree","body","Or run specship init -i to index your specs/ folder if you haven't yet."],[3,"close","open"],[2,"color","var(--text-primary)"],[2,"color","var(--text-muted)"],[2,"color","var(--warn)"],[1,"doc-row","row","gap-6",3,"click"],[2,"color","var(--text-muted)",3,"name","size"],["name","book",2,"color","var(--node-spec)",3,"size"],[1,"mono","grow","doc-name"],[1,"pill",2,"font-size","9.5px","color","var(--warn)","background","var(--warn-soft)"],[1,"group-body"],[1,"req-row","row","gap-6",3,"selected"],[1,"req-row","row","gap-6",3,"click"],[1,"pill-dot",2,"flex-shrink","0"],[1,"grow",2,"min-width","0"],[1,"mono","req-id"],[1,"muted","req-title"],[1,"row","gap-6",2,"padding","10px 12px 2px","font-size","11px","color","var(--text-muted)"],[1,"mono","grow",2,"letter-spacing","0.5px"],[1,"tabular",2,"font-size","10.5px"],[1,"pill-dot",2,"background","var(--text-muted)","flex-shrink","0"],[1,"loading-detail"],[3,"value","path"],[1,"save-error"],[1,"save-status"],[3,"valueChange","save","cancel","value","path"],[1,"row","gap-8",2,"margin-bottom","4px"],[1,"mono",2,"font-size","12px","color","var(--node-spec)"],[3,"text"],[3,"state"],[1,"detail-title"],[1,"meta-row","row"],[1,"meta-item"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"eyebrow",2,"margin-bottom","8px"],[1,"detail-body","md-content",3,"innerHTML"],[1,"brief-panel"],[1,"skel",2,"height","42px","border-radius","8px","margin-bottom","22px"],[1,"card",2,"overflow","hidden","margin-bottom","22px"],[1,"card","card-pad","orphan-card"],[1,"row","gap-8",2,"flex-wrap","wrap"],["type","button",1,"btn","btn-primary","btn-sm"],["name","play",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","check",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","reveal",3,"size"],["name","graph",3,"size"],[1,"save-error",2,"margin-top","16px"],[1,"eyebrow","brief-summary"],[1,"detail-body","brief-body","md-content",3,"innerHTML"],[1,"row","gap-10","link-row",3,"border-top"],[1,"row","gap-10","link-row"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","grow","link-target"],["type","button",1,"btn","btn-ghost","btn-xs"],["name","drift",3,"size"],[2,"margin-top","6px","font-size","12.5px"],["action","",1,"mono",2,"font-size","11.5px","color","var(--accent)","background","var(--bg-canvas)","padding","5px 10px","border-radius","6px","border","1px solid var(--border-subtle)"]],template:function(e,i){e&1&&g(0,Me,1,0,"app-pick-project-empty",0)(1,Xe,20,7),e&2&&u(i.resource.state().noProject?0:1)},dependencies:[ee,E,F,W,ie,te,oe,ne],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.specs-shell[_ngcontent-%COMP%]{flex:1;display:flex;min-height:0}.tree-col[_ngcontent-%COMP%]{width:280px;flex-shrink:0;border-right:1px solid var(--border-subtle);background:var(--bg-panel);display:flex;flex-direction:column;min-height:0}.tree-header[_ngcontent-%COMP%]{padding:11px 12px;border-bottom:1px solid var(--border-subtle);align-items:center}.tree-scroll[_ngcontent-%COMP%]{flex:1;padding:6px}.doc-row[_ngcontent-%COMP%]{padding:6px 8px;border-radius:6px;cursor:pointer;color:var(--text-secondary);align-items:center}.doc-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.doc-name[_ngcontent-%COMP%]{font-size:12px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.group-body[_ngcontent-%COMP%]{margin-left:14px;border-left:1px solid var(--border-subtle);padding-left:6px}.req-row[_ngcontent-%COMP%]{padding:5px 8px;border-radius:6px;cursor:pointer;align-items:flex-start;background:transparent}.req-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.req-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.req-id[_ngcontent-%COMP%]{font-size:11px}.req-title[_ngcontent-%COMP%]{font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.detail-col[_ngcontent-%COMP%]{flex:1;min-width:0}.detail-scroll[_ngcontent-%COMP%]{flex:1;padding:22px}.detail-title[_ngcontent-%COMP%]{font-size:22px;font-weight:650;letter-spacing:-.01em;margin:2px 0 14px;text-wrap:pretty}.meta-row[_ngcontent-%COMP%]{gap:18px;padding:10px 0;border-top:1px solid var(--border-subtle);border-bottom:1px solid var(--border-subtle);margin-bottom:18px;flex-wrap:wrap}.detail-body[_ngcontent-%COMP%]{font-size:13.5px;line-height:1.65;color:var(--text-secondary);margin-bottom:22px;text-wrap:pretty}.brief-panel[_ngcontent-%COMP%]{border:1px solid var(--border-subtle);border-radius:8px;padding:0 12px;margin-bottom:22px;background:var(--bg-panel)}.brief-summary[_ngcontent-%COMP%]{padding:10px 0;cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;-webkit-user-select:none;user-select:none;margin-bottom:0}.brief-summary[_ngcontent-%COMP%]::-webkit-details-marker{display:none}.brief-summary[_ngcontent-%COMP%]:before{content:"\\25b6";font-size:8px;color:var(--text-muted);transition:transform .15s}details[open][_ngcontent-%COMP%] > .brief-summary[_ngcontent-%COMP%]:before{transform:rotate(90deg)}.brief-body[_ngcontent-%COMP%]{margin-bottom:12px}.link-row[_ngcontent-%COMP%]{padding:10px 12px}.link-target[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.orphan-card[_ngcontent-%COMP%]{text-align:center;color:var(--error);margin-bottom:22px;border-color:#f2555a4d}.loading-detail[_ngcontent-%COMP%]{padding:40px 18px;color:var(--text-muted);font-size:13px;text-align:center}.save-error[_ngcontent-%COMP%]{padding:10px 14px;border:1px solid rgba(255,90,90,.35);background:var(--error-soft);color:var(--error);border-radius:8px;font-size:12.5px;line-height:1.5}.save-status[_ngcontent-%COMP%]{margin-top:8px;color:var(--text-muted);font-size:12px}.md-content[_ngcontent-%COMP%] .md-h1[_ngcontent-%COMP%]{font-size:15px;font-weight:650;color:var(--text-primary);letter-spacing:-.01em;margin:0 0 10px}.md-content[_ngcontent-%COMP%] .md-h2[_ngcontent-%COMP%]{font-size:13px;font-weight:650;color:var(--text-primary);letter-spacing:-.005em;margin:18px 0 6px;padding-bottom:4px;border-bottom:1px solid var(--border-subtle)}.md-content[_ngcontent-%COMP%] .md-h3[_ngcontent-%COMP%]{font-size:12px;font-weight:650;color:var(--text-primary);margin:14px 0 6px}.md-content[_ngcontent-%COMP%] .md-h4[_ngcontent-%COMP%]{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin:12px 0 4px}.md-content[_ngcontent-%COMP%] .md-p[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.6;color:var(--text-secondary);margin:0 0 4px;overflow-wrap:anywhere}.md-content[_ngcontent-%COMP%] .md-p[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-primary)}.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%], .md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%]{padding:0;margin:4px 0 6px}.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%], .md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{position:relative;padding:2px 0 2px 22px;font-size:12.5px;line-height:1.6;color:var(--text-secondary);overflow-wrap:anywhere}.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-primary)}.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%]{list-style:none}.md-content[_ngcontent-%COMP%] .md-list[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:before{content:"\\2022";position:absolute;left:6px;top:2px;color:var(--text-faint)}.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%]{list-style:none;counter-reset:md-ol}.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{counter-increment:md-ol}.md-content[_ngcontent-%COMP%] .md-ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:before{content:counter(md-ol) ".";position:absolute;left:0;top:2px;color:var(--text-faint);font-family:var(--font-mono);font-size:11.5px;min-width:18px;text-align:right}.md-content[_ngcontent-%COMP%] .md-spacer[_ngcontent-%COMP%]{height:6px}.md-content[_ngcontent-%COMP%] .md-import[_ngcontent-%COMP%]{display:inline-block;font-size:11.5px;color:var(--node-route);background:var(--node-route-soft);padding:2px 8px;border-radius:5px;margin:4px 0}.md-content[_ngcontent-%COMP%] .md-inline-code[_ngcontent-%COMP%]{font-size:11.5px;background:var(--bg-canvas);padding:1px 6px;border-radius:4px;border:1px solid var(--border-subtle);color:var(--node-spec)}.md-content[_ngcontent-%COMP%] .md-blockquote[_ngcontent-%COMP%]{margin:6px 0;padding:8px 12px;border-left:3px solid var(--accent);background:var(--accent-soft);color:var(--text-secondary);font-size:12.5px;line-height:1.55;border-radius:0 6px 6px 0}.md-content[_ngcontent-%COMP%] .md-pre[_ngcontent-%COMP%]{position:relative;margin:8px 0 10px;padding:12px 14px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:8px;overflow-x:auto;max-width:100%}.md-content[_ngcontent-%COMP%] .md-pre[_ngcontent-%COMP%] code[_ngcontent-%COMP%]{display:block;font-size:11.5px;line-height:1.55;color:var(--text-primary);white-space:pre}.md-content[_ngcontent-%COMP%] .md-pre-lang[_ngcontent-%COMP%]{position:absolute;top:6px;right:10px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:lowercase;background:var(--bg-panel);padding:1px 6px;border-radius:4px;border:1px solid var(--border-subtle)}.md-content[_ngcontent-%COMP%] .md-table-scroll[_ngcontent-%COMP%]{max-width:100%;overflow-x:auto;margin:10px 0;border:1px solid var(--border-subtle);border-radius:8px}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%]{width:100%;border-collapse:collapse;font-size:11.5px}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], .md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{padding:8px 12px;text-align:left;vertical-align:top;border-bottom:1px solid var(--border-subtle)}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th[_ngcontent-%COMP%]{background:var(--bg-panel);font-weight:650;color:var(--text-primary);font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;border-bottom:1px solid var(--border-strong);white-space:nowrap}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{color:var(--text-secondary)}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%]{border-bottom:0}.md-content[_ngcontent-%COMP%] .md-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.md-content[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:first-child{margin-top:0}'],changeDetection:0})};export{pe as Specs};
@@ -0,0 +1 @@
1
+ import{a as N,b as D}from"./chunk-Y6WWDS4R.js";import{a as z}from"./chunk-UYC52MBC.js";import{a as T}from"./chunk-SUZYBYDW.js";import{a as M}from"./chunk-E44X4RH2.js";import{Aa as a,Ga as C,I as v,Ia as c,Ka as P,M as S,N as E,Ta as u,Ua as g,Va as n,W as f,Wa as b,ea as o,ka as w,qa as m,ra as x,sa as y,ua as k,va as _,wa as h,xa as s,ya as e,za as t,zb as O}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var A=(r,l)=>l.model;function B(r,l){r&1&&n(0," Enabled \u2014 popups fire while the dashboard is open or backgrounded ")}function j(r,l){r&1&&n(0," Blocked \u2014 re-enable notifications for this site in your browser settings ")}function V(r,l){r&1&&n(0," Not supported in this browser ")}function $(r,l){r&1&&n(0," Get a desktop popup when a run needs approval, finishes, or drift appears ")}function F(r,l){if(r&1){let p=C();e(0,"button",50),c("click",function(){S(p);let d=P();return E(d.enableNotifications())}),n(1,"Enable"),t()}}function L(r,l){r&1&&(e(0,"span",24),n(1,"\u25CF On"),t())}function H(r,l){r&1&&(e(0,"span",25),n(1,"\u2014"),t())}function W(r,l){if(r&1&&(e(0,"div",34)(1,"span",51),n(2),t(),a(3,"input",52)(4,"input",52),t()),r&2){let p=l.$implicit;o(2),b(p.model),o(),s("value",p.input),o(),s("value",p.output)}}function q(r,l){if(r&1&&(e(0,"option"),n(1),t()),r&2){let p=l.$implicit;o(),b(p)}}var I=class r{api=v(M);theme=v(N);notify=v(D);setTheme(l){this.theme.setPref(l)}enableNotifications(){this.notify.requestPermission()}ingest=f(!0);watch=f(!0);motion=f(!1);toggleIngest(){this.ingest.update(l=>!l)}toggleWatch(){this.watch.update(l=>!l)}toggleMotion(){this.motion.update(l=>!l)}replayIntro(){try{sessionStorage.removeItem("specship-booted")}catch{}window.location.reload()}themeOptions=[{value:"dark",label:"Dark"},{value:"light",label:"Light"},{value:"system",label:"System"}];editorOptions=["code (VS Code)","subl (Sublime)","cursor","nvim"];pricing=[{model:"claude-opus-4",input:"15.00",output:"75.00"},{model:"claude-sonnet-4",input:"3.00",output:"15.00"},{model:"claude-haiku-4",input:"0.80",output:"4.00"}];static \u0275fac=function(p){return new(p||r)};static \u0275cmp=w({type:r,selectors:[["app-settings"]],decls:183,vars:42,consts:[[1,"settings-page","scroll-y"],["icon","settings","title","Settings"],[1,"settings-body"],[1,"card","card-pad","section-card"],[1,"section-head","row","gap-8"],["name","folder",2,"color","var(--accent)",3,"size"],[1,"section-title"],[1,"field"],[1,"field-label"],["value","~/dev/specship","readonly","",1,"input","mono",2,"width","100%"],[1,"field-hint"],["value","specs/",1,"input","mono",2,"width","100%"],["value","node_modules/, dist/, .cg/wt/",1,"input","mono",2,"width","100%"],["name","sessions",2,"color","var(--accent)",3,"size"],["value","~/.claude/projects/",1,"input","mono",2,"width","100%"],[1,"toggle-row","row"],[1,"grow"],[1,"toggle-label"],[1,"muted",2,"font-size","11px"],["type","button","aria-label","Enable transcript ingest",1,"toggle-btn",3,"click"],[1,"toggle-thumb"],["type","button","aria-label","Real-time watch",1,"toggle-btn",3,"click"],["name","zap",2,"color","var(--accent)",3,"size"],["type","button",2,"height","30px","padding","0 12px","border-radius","6px","border","1px solid var(--accent)","background","var(--accent)","color","#fff","font-size","12px","cursor","pointer"],[2,"font-size","12px","color","var(--accent)"],[1,"muted",2,"font-size","12px"],["type","button","aria-label","Notify when a run needs approval",1,"toggle-btn",3,"click"],["type","button","aria-label","Notify when a run completes or fails",1,"toggle-btn",3,"click"],["type","button","aria-label","Notify when drift is detected",1,"toggle-btn",3,"click"],["type","button","aria-label","Notify when a new improvement is found",1,"toggle-btn",3,"click"],["name","dollar",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11.5px","margin-bottom","12px"],[1,"pricing-header","row"],[1,"price-col"],[1,"pricing-row","row"],["name","sparkles",2,"color","var(--accent)",3,"size"],[3,"change","value","options"],["type","button","aria-label","Reduced motion",1,"toggle-btn",3,"click"],[1,"toggle-row","row",2,"border-top","1px solid var(--border-subtle)","margin-top","4px","padding-top","8px"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","refresh",3,"size"],["name","reveal",2,"color","var(--accent)",3,"size"],[1,"input",2,"width","200px"],["name","graph",2,"color","var(--accent)",3,"size"],[1,"about-grid"],[1,"about-row","row"],[1,"mono",2,"font-size","12px"],[1,"mono",2,"font-size","12px","color","var(--success)"],[1,"status-dot",2,"background","var(--success)"],[2,"height","30px"],["type","button",2,"height","30px","padding","0 12px","border-radius","6px","border","1px solid var(--accent)","background","var(--accent)","color","#fff","font-size","12px","cursor","pointer",3,"click"],[1,"mono","grow",2,"font-size","12px"],[1,"input","mono","tabular","price-input",3,"value"]],template:function(p,i){if(p&1&&(e(0,"div",0),a(1,"app-page-head",1),e(2,"div",2)(3,"section",3)(4,"div",4),a(5,"app-icon",5),e(6,"span",6),n(7,"Project"),t()(),e(8,"div",7)(9,"label",8),n(10,"Project root"),t(),a(11,"input",9),e(12,"div",10),n(13,"Set at app open \xB7 read-only"),t()(),e(14,"div",7)(15,"label",8),n(16,"Spec roots"),t(),a(17,"input",11),t(),e(18,"div",7)(19,"label",8),n(20,"Ignore patterns"),t(),a(21,"input",12),t()(),e(22,"section",3)(23,"div",4),a(24,"app-icon",13),e(25,"span",6),n(26,"Claude Code"),t()(),e(27,"div",7)(28,"label",8),n(29,"Transcripts path"),t(),a(30,"input",14),e(31,"div",10),n(32,"Auto-detected \xB7 overridable"),t()(),e(33,"div",15)(34,"div",16)(35,"div",17),n(36,"Enable transcript ingest"),t(),e(37,"div",18),n(38,"Read JSONL transcripts for analytics"),t()(),e(39,"button",19),c("click",function(){return i.toggleIngest()}),a(40,"span",20),t()(),e(41,"div",15)(42,"div",16)(43,"div",17),n(44,"Real-time watch"),t(),e(45,"div",18),n(46,"Tail new transcript lines as they're written"),t()(),e(47,"button",21),c("click",function(){return i.toggleWatch()}),a(48,"span",20),t()()(),e(49,"section",3)(50,"div",4),a(51,"app-icon",22),e(52,"span",6),n(53,"Notifications"),t()(),e(54,"div",15)(55,"div",16)(56,"div",17),n(57,"Desktop notifications"),t(),e(58,"div",18),x(59,B,1,0)(60,j,1,0)(61,V,1,0)(62,$,1,0),t()(),x(63,F,2,0,"button",23)(64,L,2,0,"span",24)(65,H,2,0,"span",25),t(),e(66,"div",15)(67,"div",16)(68,"div",17),n(69,"Run needs approval"),t(),e(70,"div",18),n(71,"A workflow run paused at an approval gate"),t()(),e(72,"button",26),c("click",function(){return i.notify.toggle("approval")}),a(73,"span",20),t()(),e(74,"div",15)(75,"div",16)(76,"div",17),n(77,"Run completed or failed"),t(),e(78,"div",18),n(79,"A workflow run finished or errored"),t()(),e(80,"button",27),c("click",function(){return i.notify.toggle("runDone")}),a(81,"span",20),t()(),e(82,"div",15)(83,"div",16)(84,"div",17),n(85,"Drift detected"),t(),e(86,"div",18),n(87,"Spec \u2192 code drift appeared"),t()(),e(88,"button",28),c("click",function(){return i.notify.toggle("drift")}),a(89,"span",20),t()(),e(90,"div",15)(91,"div",16)(92,"div",17),n(93,"New improvement"),t(),e(94,"div",18),n(95,"A new high-severity self-improvement proposal was found"),t()(),e(96,"button",29),c("click",function(){return i.notify.toggle("reflect")}),a(97,"span",20),t()()(),e(98,"section",3)(99,"div",4),a(100,"app-icon",30),e(101,"span",6),n(102,"Pricing table"),t()(),e(103,"div",31),n(104,"Per-million-token prices. Bump these when Anthropic publishes new tiers."),t(),e(105,"div",32)(106,"span",16),n(107,"Model"),t(),e(108,"span",33),n(109,"Input $/M"),t(),e(110,"span",33),n(111,"Output $/M"),t()(),_(112,W,5,3,"div",34,A),t(),e(114,"section",3)(115,"div",4),a(116,"app-icon",35),e(117,"span",6),n(118,"Appearance"),t()(),e(119,"div",7)(120,"label",8),n(121,"Theme"),t(),e(122,"app-segmented",36),c("change",function(R){return i.setTheme(R)}),t(),e(123,"div",10),n(124,"Now fully supported \u2014 dark, light, or follow your OS"),t()(),e(125,"div",15)(126,"div",16)(127,"div",17),n(128,"Reduced motion"),t(),e(129,"div",18),n(130,"Honor OS preference \u2014 instant transitions"),t()(),e(131,"button",37),c("click",function(){return i.toggleMotion()}),a(132,"span",20),t()(),e(133,"div",38)(134,"div",16)(135,"div",17),n(136,"Boot animation"),t(),e(137,"div",18),n(138,"The graph-assembly splash on app launch"),t()(),e(139,"button",39),c("click",function(){return i.replayIntro()}),a(140,"app-icon",40),n(141," Replay intro "),t()()(),e(142,"section",3)(143,"div",4),a(144,"app-icon",41),e(145,"span",6),n(146,"Editor"),t()(),e(147,"div",7)(148,"label",8),n(149,"Open files with"),t(),e(150,"select",42),_(151,q,2,1,"option",null,k),t(),e(153,"div",10),n(154,"Detected via code / subl / etc."),t()()(),e(155,"section",3)(156,"div",4),a(157,"app-icon",43),e(158,"span",6),n(159,"About"),t()(),e(160,"div",44)(161,"div",45)(162,"span",25),n(163,"Version"),t(),e(164,"span",46),n(165,"0.4.0"),t()(),e(166,"div",45)(167,"span",25),n(168,"MCP server"),t(),e(169,"span",47),a(170,"span",48),n(171,"running "),t()(),e(172,"div",45)(173,"span",25),n(174,"Backend"),t(),e(175,"span",46),n(176),t()(),e(177,"div",45)(178,"span",25),n(179,"Log path"),t(),e(180,"span",46),n(181,"~/.cg/logs/desktop.log"),t()()()(),a(182,"div",49),t()()),p&2){let d;o(5),s("size",15),o(19),s("size",15),o(15),g("on",i.ingest()),m("aria-pressed",i.ingest()),o(8),g("on",i.watch()),m("aria-pressed",i.watch()),o(4),s("size",15),o(8),y((d=i.notify.permission())==="granted"?59:d==="denied"?60:d==="unsupported"?61:62),o(4),y(i.notify.permission()==="default"?63:i.notify.permission()==="granted"?64:65),o(3),u("opacity",i.notify.granted()?"1":"0.5"),o(6),g("on",i.notify.enabled("approval")),m("aria-pressed",i.notify.enabled("approval")),o(2),u("opacity",i.notify.granted()?"1":"0.5"),o(6),g("on",i.notify.enabled("runDone")),m("aria-pressed",i.notify.enabled("runDone")),o(2),u("opacity",i.notify.granted()?"1":"0.5"),o(6),g("on",i.notify.enabled("drift")),m("aria-pressed",i.notify.enabled("drift")),o(2),u("opacity",i.notify.granted()?"1":"0.5"),o(6),g("on",i.notify.enabled("reflect")),m("aria-pressed",i.notify.enabled("reflect")),o(4),s("size",15),o(12),h(i.pricing),o(4),s("size",15),o(6),s("value",i.theme.pref())("options",i.themeOptions),o(9),g("on",i.motion()),m("aria-pressed",i.motion()),o(9),s("size",13),o(4),s("size",15),o(7),h(i.editorOptions),o(6),s("size",15),o(19),b(i.api.isConfigured?i.api.apiBase:"not configured")}},dependencies:[O,z,T],styles:["[_nghost-%COMP%]{display:flex;flex:1;min-height:0}.settings-page[_ngcontent-%COMP%]{flex:1;padding:18px;overflow-y:auto}.settings-body[_ngcontent-%COMP%]{max-width:720px}.section-card[_ngcontent-%COMP%]{margin-bottom:14px}.section-head[_ngcontent-%COMP%]{align-items:center;margin-bottom:14px;padding-bottom:12px;border-bottom:1px solid var(--border-subtle)}.section-title[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px}.field[_ngcontent-%COMP%]{margin-bottom:16px}.field-label[_ngcontent-%COMP%]{display:block;font-size:12.5px;font-weight:500;margin-bottom:6px;color:var(--text-primary)}.field-hint[_ngcontent-%COMP%]{color:var(--text-muted);font-size:11px;margin-top:5px}.toggle-row[_ngcontent-%COMP%]{align-items:center;padding:8px 0}.toggle-label[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500}.toggle-btn[_ngcontent-%COMP%]{width:36px;height:20px;border-radius:999px;border:none;cursor:pointer;padding:2px;background:var(--bg-elevated);display:flex;justify-content:flex-start;align-items:center;transition:background .12s;flex-shrink:0}.toggle-btn.on[_ngcontent-%COMP%]{background:var(--accent);justify-content:flex-end}.toggle-btn[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.toggle-thumb[_ngcontent-%COMP%]{width:16px;height:16px;border-radius:50%;background:#fff;flex-shrink:0}.pricing-header[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em;font-weight:600;margin-bottom:6px}.pricing-row[_ngcontent-%COMP%]{padding:6px 0;border-top:1px solid var(--border-subtle);align-items:center;gap:10px}.price-col[_ngcontent-%COMP%]{width:110px;text-align:right}.price-input[_ngcontent-%COMP%]{width:100px;text-align:right;padding:4px 8px}.about-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:10px 20px}.about-row[_ngcontent-%COMP%]{justify-content:space-between;padding:5px 0;border-bottom:1px solid var(--border-subtle)}.status-dot[_ngcontent-%COMP%]{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:6px;vertical-align:middle}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1}"],changeDetection:0})};export{I as Settings};