@selvakumaresra/specship 0.1.2 → 0.3.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.
- package/README.md +2 -2
- package/commands/ss-design-implement.md +79 -0
- package/commands/{cg-drifted.md → ss-drifted.md} +2 -2
- package/commands/{cg-fix.md → ss-fix.md} +1 -1
- package/commands/{cg-implement.md → ss-implement.md} +1 -1
- package/commands/ss-spec-author.md +43 -0
- package/commands/ss-spec-review.md +48 -0
- package/dist/bin/specship.js +6 -5
- package/dist/bin/specship.js.map +1 -1
- package/dist/db/index.d.ts +3 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +5 -2
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +36 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.sql +9 -0
- package/dist/directory.d.ts +13 -3
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +17 -3
- package/dist/directory.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +16 -10
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/targets/claude.d.ts +11 -1
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +59 -2
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/server/ingest/ingestor.js +117 -17
- package/dist/server/routes/claude.js +394 -6
- package/dist/server/routes/graph.js +62 -0
- package/dist/server/routes/spec.js +161 -1
- package/dist/server/routes/status.js +77 -0
- package/dist/server/routes/workflow.js +31 -3
- package/dist/web/chunk-2AJCHB7P.js +1 -0
- package/dist/web/chunk-2CPLUFCH.js +2 -0
- package/dist/web/chunk-2DHIGIOI.js +1 -0
- package/dist/web/chunk-2GBEK2GM.js +1 -0
- package/dist/web/chunk-2I7L37NS.js +1 -0
- package/dist/web/chunk-2NAWAJB5.js +1 -0
- package/dist/web/chunk-2OJBIPE4.js +1 -0
- package/dist/web/chunk-2OKMB4KX.js +2 -0
- package/dist/web/chunk-3E2WB6D5.js +1 -0
- package/dist/web/chunk-3EBFYSCH.js +2 -0
- package/dist/web/chunk-3QCQ4BXS.js +1 -0
- package/dist/web/chunk-3SEJX2BK.js +1 -0
- package/dist/web/chunk-42XVAQ6I.js +1 -0
- package/dist/web/chunk-4IMMPEYM.js +1 -0
- package/dist/web/chunk-4N5DWG46.js +1 -0
- package/dist/web/chunk-4TJQJPCZ.js +1 -0
- package/dist/web/chunk-4WZIHTPC.js +1 -0
- package/dist/web/chunk-4YVSYOSD.js +1 -0
- package/dist/web/chunk-5BQIOYKW.js +1 -0
- package/dist/web/chunk-5HGWHUJA.js +1 -0
- package/dist/web/chunk-5Y244R4G.js +1 -0
- package/dist/web/chunk-6RRDPT5Z.js +1 -0
- package/dist/web/chunk-6VKB2ZWM.js +1 -0
- package/dist/web/chunk-7DMFVTU4.js +1 -0
- package/dist/web/chunk-7RNS77UP.js +1 -0
- package/dist/web/chunk-7SMPKVEP.js +1 -0
- package/dist/web/chunk-AZJVTPLU.js +1 -0
- package/dist/web/chunk-BCZM5AXU.js +1 -0
- package/dist/web/chunk-BLBRMCN2.js +1 -0
- package/dist/web/chunk-BMIAXD2V.js +2 -0
- package/dist/web/chunk-BPECIDVO.js +1 -0
- package/dist/web/chunk-BUXWEHIY.js +1 -0
- package/dist/web/chunk-BYZFQSM6.js +1 -0
- package/dist/web/chunk-DA6SNNAF.js +1 -0
- package/dist/web/chunk-DLQPZWSI.css +1 -0
- package/dist/web/chunk-DTRN7FZR.js +1 -0
- package/dist/web/chunk-DYRFLPJA.js +1 -0
- package/dist/web/chunk-E3J3CXR5.js +1 -0
- package/dist/web/chunk-E44X4RH2.js +1 -0
- package/dist/web/chunk-E73OX2P7.js +1 -0
- package/dist/web/chunk-EAXRKDLV.js +1 -0
- package/dist/web/chunk-EBKKDHYI.js +1 -0
- package/dist/web/chunk-EE7V7Q5P.js +1 -0
- package/dist/web/chunk-EKY2FUHU.js +1 -0
- package/dist/web/chunk-EMGMOEVR.js +1 -0
- package/dist/web/chunk-EP6XOPXH.js +1 -0
- package/dist/web/chunk-ESGDLJOJ.js +1 -0
- package/dist/web/chunk-ETJG7NCY.js +1 -0
- package/dist/web/chunk-EUUEFEDI.js +1 -0
- package/dist/web/chunk-FGNZDHTL.js +11 -0
- package/dist/web/chunk-FIJW2UNJ.js +1 -0
- package/dist/web/chunk-FMV5PXRC.js +5 -0
- package/dist/web/chunk-G7VZT5KB.js +3 -0
- package/dist/web/chunk-GRZYXPSO.js +7 -0
- package/dist/web/chunk-GYGPS3AN.js +1 -0
- package/dist/web/chunk-H7AF7YS4.js +1 -0
- package/dist/web/chunk-HDZDQILN.js +1 -0
- package/dist/web/chunk-HMK6UO6N.js +1 -0
- package/dist/web/chunk-HZA6NEAB.js +1 -0
- package/dist/web/chunk-IHEE5NYJ.js +1 -0
- package/dist/web/chunk-ISNEBICW.js +1 -0
- package/dist/web/chunk-J2GZVLHH.js +1 -0
- package/dist/web/chunk-JFYVCXK3.js +1 -0
- package/dist/web/chunk-JN6W7HCN.js +17 -0
- package/dist/web/chunk-JT7P3DEK.js +6 -0
- package/dist/web/chunk-JTFXTIPE.js +903 -0
- package/dist/web/chunk-L37MTFSG.js +3 -0
- package/dist/web/chunk-LB6JPLX2.js +1 -0
- package/dist/web/chunk-LNSVDHCI.js +1 -0
- package/dist/web/chunk-LV4G6QFG.js +2 -0
- package/dist/web/chunk-LVGIY3SO.js +1 -0
- package/dist/web/chunk-LXLHIHEN.js +1 -0
- package/dist/web/chunk-MC4DFIHG.js +1 -0
- package/dist/web/chunk-MVOMVPYB.js +1 -0
- package/dist/web/chunk-N6SS4G6S.js +1 -0
- package/dist/web/chunk-NTBJG6SJ.js +1 -0
- package/dist/web/chunk-NUDB3Q2Y.js +3 -0
- package/dist/web/chunk-OXEF5E3E.js +1 -0
- package/dist/web/chunk-PDN6QYGJ.js +4 -0
- package/dist/web/chunk-PGGJPDJG.js +1 -0
- package/dist/web/chunk-PUYSJNJR.js +1 -0
- package/dist/web/chunk-Q2RVFS45.js +1 -0
- package/dist/web/chunk-Q7L6LLAK.js +1 -0
- package/dist/web/chunk-QCMKJIWY.js +1 -0
- package/dist/web/chunk-QH6CF3M3.js +1 -0
- package/dist/web/chunk-QQ5LD7PI.js +1 -0
- package/dist/web/chunk-QR6L3KAC.js +1 -0
- package/dist/web/chunk-R2DLK4HO.js +1 -0
- package/dist/web/chunk-R5W2MDZN.js +1 -0
- package/dist/web/chunk-RAAMPHPJ.js +1 -0
- package/dist/web/chunk-RD6TVPOT.js +1 -0
- package/dist/web/chunk-RKY4EJYJ.js +1 -0
- package/dist/web/chunk-RONYWVY7.js +1 -0
- package/dist/web/chunk-RXKXYF2C.js +1 -0
- package/dist/web/chunk-SBWU7JFC.js +1 -0
- package/dist/web/chunk-SEXBRGYK.js +1 -0
- package/dist/web/chunk-SHPTC4RL.js +1 -0
- package/dist/web/chunk-SUZYBYDW.js +1 -0
- package/dist/web/chunk-SWKJRNYY.js +1 -0
- package/dist/web/chunk-T66XVKGB.js +1 -0
- package/dist/web/chunk-T7AZ65JP.js +1 -0
- package/dist/web/chunk-TCZDVOHD.js +1 -0
- package/dist/web/chunk-TPTITA3V.js +1 -0
- package/dist/web/chunk-TR335633.js +1 -0
- package/dist/web/chunk-TWXZK6XM.js +1 -0
- package/dist/web/chunk-UR5KDXPX.js +1 -0
- package/dist/web/chunk-UR6O2GEH.js +1 -0
- package/dist/web/chunk-UTNMGWTP.js +1 -0
- package/dist/web/chunk-UYC52MBC.js +1 -0
- package/dist/web/chunk-VECWMHJP.js +1 -0
- package/dist/web/chunk-VUACT35R.js +3 -0
- package/dist/web/chunk-VZI7H4SZ.js +1 -0
- package/dist/web/chunk-WAI2JMZP.js +1 -0
- package/dist/web/chunk-WB6YHOD4.js +1 -0
- package/dist/web/chunk-WBT64AWV.js +1 -0
- package/dist/web/chunk-WDU3WICG.js +1 -0
- package/dist/web/chunk-WFXJIXZE.js +4 -0
- package/dist/web/chunk-WTGYRH3Z.js +298 -0
- package/dist/web/chunk-WXTCVDTP.js +1 -0
- package/dist/web/chunk-X2HTISHL.js +1 -0
- package/dist/web/chunk-XCDHWLVH.js +1 -0
- package/dist/web/chunk-Y3H6FFUZ.js +1 -0
- package/dist/web/chunk-Y4F5ULGJ.js +1 -0
- package/dist/web/chunk-YAWCRPHV.js +1 -0
- package/dist/web/chunk-YEGKAAEE.js +1 -0
- package/dist/web/chunk-YM2KU57F.js +1 -0
- package/dist/web/chunk-YRERBP6T.js +1 -0
- package/dist/web/chunk-ZLV4VCDG.js +3 -0
- package/dist/web/chunk-ZTVI5KFF.js +1 -0
- package/dist/web/index.html +3 -3
- package/dist/web/main-ESADRXN2.css +1 -0
- package/dist/web/main-WVI3YTDU.js +1 -0
- package/dist/web/media/codicon-LN6W7LCM.ttf +0 -0
- package/dist/web/styles-KSOPUVDA.css +1 -0
- package/dist/workflows/defaults/claude-design-implement.yaml +247 -0
- package/dist/workflows/defaults/spec-author.yaml +214 -0
- package/dist/workflows/executor.d.ts.map +1 -1
- package/dist/workflows/executor.js +4 -3
- package/dist/workflows/executor.js.map +1 -1
- package/package.json +8 -3
- package/scripts/offline-install.sh +19 -6
- package/scripts/sync-shim-version.mjs +64 -0
- package/dist/web/chunk-2YZXEHZ2.js +0 -1
- package/dist/web/chunk-3GIC555L.js +0 -18
- package/dist/web/chunk-3IIIGRMT.js +0 -1
- package/dist/web/chunk-47QYKLE5.js +0 -1
- package/dist/web/chunk-4LHBWWP7.js +0 -1
- package/dist/web/chunk-4OAZLD5W.js +0 -1
- package/dist/web/chunk-5OQKAJAE.js +0 -1
- package/dist/web/chunk-7B525GKQ.js +0 -1
- package/dist/web/chunk-BPDXCOOZ.js +0 -1
- package/dist/web/chunk-DT37HTZB.js +0 -1
- package/dist/web/chunk-EIMUHJND.js +0 -1
- package/dist/web/chunk-FTESTUEO.js +0 -1
- package/dist/web/chunk-GLJZV6MU.js +0 -1
- package/dist/web/chunk-I7LS67U5.js +0 -1
- package/dist/web/chunk-L4TVIPSR.js +0 -1
- package/dist/web/chunk-MASCULC2.js +0 -1
- package/dist/web/chunk-MW7ICSRM.js +0 -1
- package/dist/web/chunk-OI5VP2A3.js +0 -1
- package/dist/web/chunk-RA6EBF6I.js +0 -1
- package/dist/web/chunk-RP3WU5Y6.js +0 -1
- package/dist/web/chunk-RQDRMTXN.js +0 -1
- package/dist/web/chunk-TQMT6UDU.js +0 -1
- package/dist/web/chunk-U7IYOV7T.js +0 -1
- package/dist/web/chunk-UE227MWF.js +0 -1
- package/dist/web/chunk-WV573J4K.js +0 -1
- package/dist/web/chunk-WVCKOJZL.js +0 -4
- package/dist/web/chunk-XZKLVPHE.js +0 -1
- package/dist/web/chunk-ZABKKHJ3.js +0 -1
- package/dist/web/main-RI5CO5Z4.js +0 -1
- package/dist/web/styles-CYN7IKT4.css +0 -1
- /package/commands/{cg-explore.md → ss-explore.md} +0 -0
- /package/commands/{cg-impact.md → ss-impact.md} +0 -0
- /package/commands/{cg-relink.md → ss-relink.md} +0 -0
- /package/commands/{cg-spec.md → ss-spec.md} +0 -0
- /package/commands/{cg-sync.md → ss-sync.md} +0 -0
- /package/commands/{cg-trace.md → ss-trace.md} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as $}from"./chunk-SBWU7JFC.js";import{a as me,b as F}from"./chunk-4N5DWG46.js";import{b as se,c as B,d as de,e as pe,f as ce}from"./chunk-SHPTC4RL.js";import{a as j}from"./chunk-7RNS77UP.js";import{a as A}from"./chunk-E44X4RH2.js";import{$ as ne,Aa as p,Ba as d,Ca as c,Da as C,Ga as k,Ha as J,I as v,Ia as h,Ja as R,Ka as m,M as y,N as P,O as Q,R as ee,Ta as oe,Ua as M,V as te,Va as l,W as T,Wa as b,Xa as X,Ya as ae,ca as ie,cb as re,da as Y,ea as o,ka as x,lb as I,ob as N,pb as S,qa as w,ra as g,sa as u,va as O,wa as E,wb as le,xa as f,ya as a,za as r,zb as D}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var ge=[{path:"",pathMatch:"full",redirectTo:"dashboard"},{path:"dashboard",loadComponent:()=>import("./chunk-2OKMB4KX.js").then(e=>e.Dashboard),data:{nav:"dashboard",title:"Dashboard"}},{path:"graph",loadComponent:()=>import("./chunk-JFYVCXK3.js").then(e=>e.Graph),data:{nav:"graph",title:"Graph"}},{path:"specs",loadComponent:()=>import("./chunk-JT7P3DEK.js").then(e=>e.Specs),data:{nav:"specs",title:"Specs"}},{path:"drift",loadComponent:()=>import("./chunk-3SEJX2BK.js").then(e=>e.Drift),data:{nav:"drift",title:"Drift queue"}},{path:"workflows",loadComponent:()=>import("./chunk-YAWCRPHV.js").then(e=>e.Workflows),data:{nav:"workflows",title:"Workflows"}},{path:"runs",loadComponent:()=>import("./chunk-BCZM5AXU.js").then(e=>e.Runs),data:{nav:"runs",title:"Runs"}},{path:"runs/:id",loadComponent:()=>import("./chunk-MVOMVPYB.js").then(e=>e.RunDetail),data:{nav:"runs",title:"Run detail"}},{path:"chat",loadComponent:()=>import("./chunk-L37MTFSG.js").then(e=>e.Chat),data:{nav:"chat",title:"Chat"}},{path:"sessions",loadComponent:()=>import("./chunk-2DHIGIOI.js").then(e=>e.Sessions),data:{nav:"sessions",title:"Sessions"}},{path:"sessions/:id",loadComponent:()=>import("./chunk-DA6SNNAF.js").then(e=>e.SessionDetail),data:{nav:"sessions",title:"Session detail"}},{path:"heatmap",loadComponent:()=>import("./chunk-LV4G6QFG.js").then(e=>e.Heatmap),data:{nav:"heatmap",title:"Heatmap"}},{path:"costs",loadComponent:()=>import("./chunk-TWXZK6XM.js").then(e=>e.Costs),data:{nav:"costs",title:"Costs"}},{path:"compare",loadComponent:()=>import("./chunk-BPECIDVO.js").then(e=>e.Compare),data:{nav:"compare",title:"Compare projects"}},{path:"tips",loadComponent:()=>import("./chunk-RAAMPHPJ.js").then(e=>e.Tips),data:{nav:"tips",title:"Tips"}},{path:"memory",loadComponent:()=>import("./chunk-JN6W7HCN.js").then(e=>e.Memory),data:{nav:"memory",title:"Memory"}},{path:"design",loadComponent:()=>import("./chunk-WAI2JMZP.js").then(e=>e.Design),data:{nav:"design",title:"Design system"}},{path:"settings",loadComponent:()=>import("./chunk-BYZFQSM6.js").then(e=>e.Settings),data:{nav:"settings",title:"Settings"}},{path:"**",redirectTo:"dashboard"}];var ue={providers:[te(),ce(ge)]};function fe(e,n){e&1&&(Q(),C(0,"rect",14)(1,"rect",15))}var V=class e{size=S(24);tile=S(!0);glow=S(!0);static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-logo-mark"]],inputs:{size:[1,"size"],tile:[1,"tile"],glow:[1,"glow"]},decls:16,vars:5,consts:[["viewBox","0 0 32 32","fill","none",2,"flex-shrink","0"],["id","ssTile","x1","0","y1","0","x2","32","y2","32","gradientUnits","userSpaceOnUse"],["stop-color","#12161E"],["offset","1","stop-color","#0B0D11"],["id","ssLead","x1","18","y1","11","x2","26","y2","21","gradientUnits","userSpaceOnUse"],["stop-color","#6FA0F6"],["offset","1","stop-color","#5B93F2"],["transform","translate(4.6 4.6) scale(0.715)"],["d","M5 16 H11 M11 9 L23 16 L11 23","stroke","rgba(150,165,200,0.5)","stroke-width","1.9","stroke-linecap","round","stroke-linejoin","round","fill","none"],["x1","11","y1","9","x2","11","y2","23","stroke","rgba(150,165,200,0.4)","stroke-width","1.9","stroke-linecap","round"],["cx","23","cy","16","r","3.6","fill","url(#ssLead)"],["cx","11","cy","9","r","2.9","fill","#A586F5"],["cx","11","cy","23","r","2.9","fill","#46C26B"],["cx","5","cy","16","r","2.1","fill","#29D2BE"],["width","32","height","32","rx","7.2","fill","url(#ssTile)"],["x","0.5","y","0.5","width","31","height","31","rx","6.7","fill","none","stroke","rgba(255,255,255,0.08)"]],template:function(t,i){t&1&&(Q(),d(0,"svg",0)(1,"defs")(2,"linearGradient",1),C(3,"stop",2)(4,"stop",3),c(),d(5,"linearGradient",4),C(6,"stop",5)(7,"stop",6),c()(),g(8,fe,2,0),d(9,"g",7),C(10,"path",8)(11,"line",9)(12,"circle",10)(13,"circle",11)(14,"circle",12)(15,"circle",13),c()()),t&2&&(oe("filter",i.glow()?"drop-shadow(0 0 9px rgba(91,147,242,0.35))":"none"),w("width",i.size())("height",i.size()),o(8),u(i.tile()?8:-1))},styles:["[_nghost-%COMP%]{display:inline-flex;align-items:center;justify-content:center;line-height:0}"],changeDetection:0})};var be=e=>["/",e],ve=(e,n)=>n.group,_e=(e,n)=>n.id;function xe(e,n){e&1&&(a(0,"div",3),l(1,"SpecShip "),a(2,"span",14),l(3,"Desktop"),r()())}function he(e,n){if(e&1&&(a(0,"div",15),l(1),r()),e&2){let t=m().$implicit;o(),b(t.group)}}function Ce(e,n){if(e&1&&(a(0,"span",18),l(1),r()),e&2){let t=m(2).$implicit,i=m(2);w("data-kind",t.badgeKind),o(),b(i.badgeOf(t))}}function ye(e,n){if(e&1&&(a(0,"span",11),l(1),r(),g(2,Ce,2,2,"span",18)),e&2){let t=m().$implicit,i=m(2);o(),b(t.label),o(),u(i.badgeOf(t)>0?2:-1)}}function Pe(e,n){if(e&1&&(a(0,"a",16),p(1,"span",8),a(2,"span",9),p(3,"app-icon",17),r(),g(4,ye,3,2),r()),e&2){let t=n.$implicit,i=m(2);f("routerLink",re(5,be,t.id))("title",i.collapsed()?t.label:null),o(3),f("name",t.icon)("size",16),o(),u(i.collapsed()?-1:4)}}function ke(e,n){if(e&1&&(a(0,"div",5),g(1,he,2,1,"div",15),O(2,Pe,5,7,"a",16,_e),r()),e&2){let t=n.$implicit,i=m();o(),u(i.collapsed()?-1:1),o(),E(t.items)}}function we(e,n){e&1&&(a(0,"span",11),l(1,"Design system"),r())}function Me(e,n){e&1&&(a(0,"span",11),l(1,"Settings"),r())}var H=class e{collapsed=S(!1);api=v(A);projects=v(j);status=F(this.api,()=>`/api/status${this.projects.projectQuery()}`);tips=F(this.api,()=>"/api/claude/tips");nav=[{group:"Project",items:[{id:"dashboard",label:"Dashboard",icon:"dashboard"},{id:"graph",label:"Graph",icon:"graph"},{id:"specs",label:"Specs",icon:"book"},{id:"drift",label:"Drift queue",icon:"drift",badge:()=>this.status.state().data?.drift??0,badgeKind:"warn"},{id:"workflows",label:"Workflows",icon:"workflow"},{id:"runs",label:"Runs",icon:"play"},{id:"chat",label:"Chat",icon:"chat"}]},{group:"Claude Code",items:[{id:"sessions",label:"Sessions",icon:"sessions"},{id:"heatmap",label:"Heatmap",icon:"heatmap"},{id:"costs",label:"Costs",icon:"dollar"},{id:"compare",label:"Compare projects",icon:"compare"},{id:"memory",label:"Memory",icon:"memory"},{id:"tips",label:"Tips",icon:"tips",badge:()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity!=="info").length,badgeKind:"error"}]}];badgeOf(n){return n.badge?n.badge():0}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-sidebar"]],inputs:{collapsed:[1,"collapsed"]},decls:18,vars:10,consts:[[1,"sidebar"],[1,"brand"],[3,"size"],[1,"brand-text"],[1,"scroll-y","nav-scroll"],[1,"nav-group"],[1,"pinned"],["routerLink","/design","routerLinkActive","active",1,"nav-item",3,"title"],[1,"indicator"],[1,"nav-icon"],["name","palette",3,"size"],[1,"nav-label"],["routerLink","/settings","routerLinkActive","active",1,"nav-item",3,"title"],["name","settings",3,"size"],[1,"muted"],[1,"eyebrow","group-label"],["routerLinkActive","active",1,"nav-item",3,"routerLink","title"],[3,"name","size"],[1,"badge"]],template:function(t,i){t&1&&(a(0,"nav",0)(1,"div",1),p(2,"app-logo-mark",2),g(3,xe,4,0,"div",3),r(),a(4,"div",4),O(5,ke,4,1,"div",5,ve),r(),a(7,"div",6)(8,"a",7),p(9,"span",8),a(10,"span",9),p(11,"app-icon",10),r(),g(12,we,2,0,"span",11),r(),a(13,"a",12),p(14,"span",8),a(15,"span",9),p(16,"app-icon",13),r(),g(17,Me,2,0,"span",11),r()()()),t&2&&(M("collapsed",i.collapsed()),o(2),f("size",26),o(),u(i.collapsed()?-1:3),o(2),E(i.nav),o(3),f("title",i.collapsed()?"Design system":null),o(3),f("size",16),o(),u(i.collapsed()?-1:12),o(),f("title",i.collapsed()?"Settings":null),o(3),f("size",16),o(),u(i.collapsed()?-1:17))},dependencies:[de,pe,D,V],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.sidebar[_ngcontent-%COMP%]{width:var(--sidebar-w);flex-shrink:0;background:var(--bg-panel);border-right:1px solid var(--border-subtle);display:flex;flex-direction:column;transition:width .12s;overflow:hidden;font-family:var(--font-ui)}.sidebar.collapsed[_ngcontent-%COMP%]{width:var(--sidebar-w-collapsed)}.brand[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;padding:15px 16px}.collapsed[_ngcontent-%COMP%] .brand[_ngcontent-%COMP%]{justify-content:center;padding:14px 0}.brand-text[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px;letter-spacing:-.01em}.brand-text[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted);font-weight:400}.nav-scroll[_ngcontent-%COMP%]{flex:1;padding:4px 8px}.nav-group[_ngcontent-%COMP%]{margin-bottom:10px}.group-label[_ngcontent-%COMP%]{padding:8px 8px 4px}.nav-item[_ngcontent-%COMP%]{position:relative;display:flex;align-items:center;gap:10px;height:32px;padding:0 10px;border-radius:7px;text-decoration:none;margin-bottom:1px;color:var(--text-secondary);font-weight:450;font-size:13px;transition:background .1s}.collapsed[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%]{padding:0;justify-content:center}.nav-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%]{background:var(--bg-active);color:var(--text-primary);font-weight:600}.nav-item.active[_ngcontent-%COMP%] .indicator[_ngcontent-%COMP%]{position:absolute;left:0;top:7px;bottom:7px;width:2.5px;border-radius:2px;background:var(--accent)}.nav-icon[_ngcontent-%COMP%]{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--text-secondary)}.nav-item[_ngcontent-%COMP%]:hover .nav-icon[_ngcontent-%COMP%]{color:var(--text-primary)}.nav-item.active[_ngcontent-%COMP%] .nav-icon[_ngcontent-%COMP%]{color:var(--accent)}.nav-label[_ngcontent-%COMP%]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.badge[_ngcontent-%COMP%]{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10px;font-weight:700;padding:1px 6px;min-width:18px;border-radius:999px;display:inline-flex;justify-content:center;color:var(--text-secondary);background:#ffffff0f}.badge[data-kind=error][_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.badge[data-kind=warn][_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pinned[_ngcontent-%COMP%]{padding:8px;border-top:1px solid var(--border-subtle)}'],changeDetection:0})};function Se(e,n){e&1&&(d(0,"span",8),l(1,"\u26A0"),c()),e&2&&J("title",n)}function Oe(e,n){if(e&1){let t=k();d(0,"span",2),l(1),c(),C(2,"span",3),d(3,"span",4)(4,"span",5),l(5,"backend"),c(),d(6,"span",6),l(7),c()(),C(8,"span",3),d(9,"span",4)(10,"span",5),l(11,"nodes"),c(),d(12,"span",6),l(13),c()(),d(14,"span",4)(15,"span",5),l(16,"edges"),c(),d(17,"span",6),l(18),c()(),C(19,"span",3),d(20,"span",4)(21,"span",5),l(22,"drift"),c(),d(23,"span",6),l(24),c()(),C(25,"span",7),d(26,"span",4)(27,"span",5),l(28,"indexed"),c(),d(29,"span",6),l(30),c()(),g(31,Se,2,1,"span",8),d(32,"button",9),R("click",function(){y(t);let s=m();return P(s.refresh())}),l(33,"\u21BB"),c()}if(e&2){let t,i=m(),s=i.status.state().data;o(),b(s.projectPath),o(6),b(s.backend),o(6),b(s.nodeCount.toLocaleString()),o(5),b(s.edgeCount.toLocaleString()),o(5),M("warn",s.drift>0)("success",s.drift===0),o(),b(s.drift),o(6),b(i.indexedLabel()),o(),u((t=i.refreshSvc.error())?31:-1,t),o(),M("spinning",i.refreshSvc.loading()),J("disabled",i.refreshSvc.loading())("title",i.refreshSvc.loading()?"Refreshing\u2026":"Refresh: sync index + re-ingest Claude Code transcripts. Updates Sessions, Heatmap, Costs, Memory, Drift, Graph."),w("aria-label",i.refreshSvc.loading()?"Refreshing\u2026":"Refresh everything \u2014 sync index + ingest Claude Code transcripts")}}function Ee(e,n){e&1&&(d(0,"span",1),l(1,"loading status\u2026"),c())}function Te(e,n){e&1&&(d(0,"span",1),l(1,"no backend"),c())}var G=class e{api=v(A);projects=v(j);refreshSvc=v(me);status=F(this.api,()=>`/api/status${this.projects.projectQuery()}`);indexedLabel=I(()=>{let n=this.status.state().data?.lastIndexed;if(!n)return"never";try{let t=new Date(n),i=Date.now()-t.getTime();return i<6e4?"just now":i<36e5?`${Math.round(i/6e4)}m ago`:i<864e5?`${Math.round(i/36e5)}h ago`:t.toLocaleDateString()}catch{return String(n)}});async refresh(){await this.refreshSvc.triggerGlobalRefresh()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-status-strip"]],decls:4,vars:1,consts:[[1,"status-strip"],[1,"mono","muted"],[1,"seg","mono"],[1,"divider"],[1,"seg"],[1,"lbl"],[1,"mono","val"],[1,"grow"],[1,"refresh-error","mono",3,"title"],[1,"refresh",3,"click","disabled","title"]],template:function(t,i){t&1&&(d(0,"div",0),g(1,Oe,34,16)(2,Ee,2,0,"span",1)(3,Te,2,0,"span",1),c()),t&2&&(o(),u(i.status.state().data?1:i.status.state().loading?2:3))},styles:["[_nghost-%COMP%]{display:contents}.status-strip[_ngcontent-%COMP%]{height:var(--status-h);flex-shrink:0;display:flex;align-items:center;gap:14px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-panel-2);font-size:11.5px;overflow:hidden;white-space:nowrap}.seg[_ngcontent-%COMP%]{display:flex;align-items:center;gap:6px;flex-shrink:0}.lbl[_ngcontent-%COMP%]{color:var(--text-muted);font-size:11px}.val[_ngcontent-%COMP%]{color:var(--text-secondary);font-variant-numeric:tabular-nums}.val.warn[_ngcontent-%COMP%]{color:var(--warn)}.val.success[_ngcontent-%COMP%]{color:var(--success)}.divider[_ngcontent-%COMP%]{width:1px;height:12px;background:var(--border-subtle);flex-shrink:0}.grow[_ngcontent-%COMP%]{flex:1}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.refresh[_ngcontent-%COMP%]{background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:14px;padding:2px 6px;border-radius:4px;transition:background .12s,color .12s}.refresh[_ngcontent-%COMP%]:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}.refresh[_ngcontent-%COMP%]:disabled{cursor:progress;opacity:.8}.refresh[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.refresh.spinning[_ngcontent-%COMP%]{display:inline-block;animation:_ngcontent-%COMP%_spin .9s linear infinite;color:var(--accent)}@keyframes _ngcontent-%COMP%_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.refresh-error[_ngcontent-%COMP%]{color:var(--warn);font-size:12px;padding:0 2px;cursor:help}"],changeDetection:0})};var je=(e,n)=>n.slug;function De(e,n){e&1&&p(0,"span",8)}function ze(e,n){e&1&&p(0,"span",9)}function Le(e,n){e&1&&p(0,"span",10)}function Re(e,n){if(e&1&&(a(0,"span",7),l(1),r(),g(2,De,1,0,"span",8)(3,ze,1,0,"span",9)(4,Le,1,0,"span",10)),e&2){let t=n,i=m();o(),b(i.shortPath(t.path)),o(),u(t.exists?t.initialized?4:3:2)}}function Ie(e,n){e&1&&(a(0,"span",3),l(1,"Select project"),r())}function Ne(e,n){if(e&1){let t=k();a(0,"button",20),h("click",function(){y(t);let s=m(2);return P(s.clear())}),p(1,"app-icon",21),l(2," Clear "),r()}e&2&&(o(),f("size",11))}function Fe(e,n){e&1&&(a(0,"span",16),l(1,"\xB7 loading\u2026"),r())}function Be(e,n){if(e&1&&(a(0,"span",16),l(1),r()),e&2){let t=m(2);o(),X("\xB7 ",t.filtered().length," shown \xB7 live")}}function Ae(e,n){e&1&&(a(0,"div",18),l(1,"No projects match."),r())}function $e(e,n){e&1&&(a(0,"span",25),l(1,"missing"),r())}function Ve(e,n){e&1&&(a(0,"span",26),l(1,"not init"),r())}function He(e,n){e&1&&(a(0,"span",27),l(1,"initialized"),r())}function Ge(e,n){if(e&1&&(a(0,"span"),l(1),r()),e&2){let t=m().$implicit,i=m(2);o(),X("\xB7 ",i.formatRelative(t.lastModifiedMs))}}function qe(e,n){e&1&&p(0,"app-icon",29),e&2&&f("size",13)}function Ke(e,n){if(e&1){let t=k();a(0,"button",22),h("click",function(){let s=y(t).$implicit,_=m(2);return P(_.pick(s.slug))}),a(1,"div",23)(2,"div",24)(3,"span",7),l(4),r(),g(5,$e,2,0,"span",25)(6,Ve,2,0,"span",26)(7,He,2,0,"span",27),r(),a(8,"div",28)(9,"span"),l(10),r(),g(11,Ge,2,1,"span"),r()(),g(12,qe,1,1,"app-icon",29),r()}if(e&2){let t=n.$implicit,i=m(2);M("active",i.projects.activeSlug()===t.slug),o(4),b(i.shortPath(t.path)),o(),u(t.exists?t.initialized?7:6:5),o(5),ae("",t.sessionCount," session",t.sessionCount===1?"":"s"),o(),u(t.lastModifiedMs>0?11:-1),o(),u(i.projects.activeSlug()===t.slug?12:-1)}}function We(e,n){if(e&1){let t=k();a(0,"div",6)(1,"div",11),p(2,"app-icon",12),a(3,"input",13),h("input",function(s){y(t);let _=m();return P(_.onQuery(s.target.value))}),r(),g(4,Ne,3,1,"button",14),r(),a(5,"div",15)(6,"span"),l(7),r(),g(8,Fe,2,0,"span",16)(9,Be,2,1,"span",16),r(),a(10,"div",17),g(11,Ae,2,0,"div",18),O(12,Ke,13,8,"button",19,je),r()()}if(e&2){let t=m();o(2),f("size",13),o(),f("value",t.query()),o(),u(t.projects.activeSlug()?4:-1),o(3),b(t.projects.claudeRoot()??"~/.claude/projects"),o(),u(t.projects.loading()?8:9),o(3),u(t.filtered().length===0&&!t.projects.loading()?11:-1),o(),E(t.filtered())}}var q=class e{host=v(ne);projects=v(j);open=T(!1);query=T("");filtered=I(()=>{let n=this.query().trim().toLowerCase(),t=this.projects.projects();return n?t.filter(i=>i.path.toLowerCase().includes(n)||i.slug.toLowerCase().includes(n)):t});badge=I(()=>this.projects.projects().length);toggle(){this.open.update(n=>!n)}pick(n){this.projects.setActive(n),this.open.set(!1),this.query.set("")}clear(){this.projects.setActive(null),this.open.set(!1)}onQuery(n){this.query.set(n)}onDocumentClick(n){if(!this.open())return;let t=n.target;t&&!this.host.nativeElement.contains(t)&&this.open.set(!1)}onEscape(){this.open()&&this.open.set(!1)}formatRelative(n){if(!n)return"";let t=Date.now()-n,i=Math.round(t/1e3);if(i<60)return`${i}s ago`;let s=Math.round(i/60);if(s<60)return`${s}m ago`;let _=Math.round(s/60);if(_<24)return`${_}h ago`;let Z=Math.round(_/24);return Z<30?`${Z}d ago`:new Date(n).toLocaleDateString()}shortPath(n){if(!n)return"";let t=this.detectHome();return t&&n===t?"~":t&&n.startsWith(t+"/")?"~/"+n.slice(t.length+1):n}detectHome(){let n=this.projects.claudeRoot();if(!n)return null;let t="/.claude/projects";return n.endsWith(t)?n.slice(0,-t.length):null}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-project-picker"]],hostBindings:function(t,i){t&1&&h("click",function(_){return i.onDocumentClick(_)},Y)("keydown.escape",function(){return i.onEscape()},Y)},decls:9,vars:9,consts:[[1,"wrap"],["type","button","aria-label","Switch project",1,"trigger",3,"click"],["name","folder",3,"size"],[1,"placeholder"],[1,"badge","mono"],[3,"name","size"],["role","dialog","aria-label","Pick a project",1,"popover"],[1,"path","mono"],["title","path no longer exists on disk",1,"status-dot","missing"],["title","not yet specship init'd",1,"status-dot","warn"],["title","initialized",1,"status-dot","ok"],[1,"popover-head","row","gap-8"],["name","search",3,"size"],["type","text","placeholder","Filter projects\u2026","autofocus","",1,"popover-input",3,"input","value"],["title","Clear selection",1,"btn","btn-ghost","btn-xs"],[1,"popover-meta","mono"],[1,"muted"],[1,"popover-list","scroll-y"],[1,"empty"],["type","button",1,"row-item",3,"active"],["title","Clear selection",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],["type","button",1,"row-item",3,"click"],[1,"col","gap-2","grow"],[1,"row","gap-6","path-line"],[1,"pill","missing"],[1,"pill","warn"],[1,"pill","ok"],[1,"meta","row","gap-8","mono","muted"],["name","check",3,"size"]],template:function(t,i){if(t&1&&(a(0,"div",0)(1,"button",1),h("click",function(){return i.toggle()}),p(2,"app-icon",2),g(3,Re,5,2)(4,Ie,2,0,"span",3),a(5,"span",4),l(6),r(),p(7,"app-icon",5),r(),g(8,We,14,6,"div",6),r()),t&2){let s;M("open",i.open()),o(),w("aria-expanded",i.open()),o(),f("size",13),o(),u((s=i.projects.active())?3:4,s),o(3),b(i.badge()),o(),f("name",i.open()?"chevronDown":"chevronRight")("size",11),o(),u(i.open()?8:-1)}},dependencies:[D],styles:["[_nghost-%COMP%]{display:inline-flex;min-width:0}.wrap[_ngcontent-%COMP%]{position:relative;min-width:0}.trigger[_ngcontent-%COMP%]{height:30px;padding:0 11px 0 10px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;color:var(--text-secondary);display:inline-flex;align-items:center;gap:8px;font-family:var(--font-ui);font-size:12.5px;cursor:pointer;max-width:360px;min-width:0;transition:background .1s,border-color .1s}.trigger[_ngcontent-%COMP%]:hover, .wrap.open[_ngcontent-%COMP%] .trigger[_ngcontent-%COMP%]{background:var(--bg-panel-2);border-color:var(--border-strong);color:var(--text-primary)}.trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.trigger[_ngcontent-%COMP%]:hover app-icon[_ngcontent-%COMP%]{color:var(--text-secondary)}.path[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.placeholder[_ngcontent-%COMP%]{color:var(--text-muted);font-style:italic}.status-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;flex-shrink:0}.status-dot.ok[_ngcontent-%COMP%]{background:var(--success)}.status-dot.warn[_ngcontent-%COMP%]{background:var(--warn)}.status-dot.missing[_ngcontent-%COMP%]{background:var(--error)}.badge[_ngcontent-%COMP%]{font-size:10px;padding:1px 6px;border-radius:999px;background:var(--bg-active);color:var(--text-muted);font-variant-numeric:tabular-nums;flex-shrink:0}.popover[_ngcontent-%COMP%]{position:absolute;top:calc(100% + 6px);left:0;z-index:30;width:420px;max-width:calc(100vw - 40px);background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:10px;box-shadow:var(--shadow-pop);display:flex;flex-direction:column;max-height:480px;animation:_ngcontent-%COMP%_pp-in .12s ease-out}@keyframes _ngcontent-%COMP%_pp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.popover-head[_ngcontent-%COMP%]{padding:10px 12px 8px;border-bottom:1px solid var(--border-subtle)}.popover-head[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted);flex-shrink:0}.popover-input[_ngcontent-%COMP%]{flex:1;min-width:0;background:transparent;border:none;outline:none;font-family:var(--font-ui);font-size:13px;color:var(--text-primary)}.popover-input[_ngcontent-%COMP%]::placeholder{color:var(--text-muted)}.popover-meta[_ngcontent-%COMP%]{padding:6px 12px 8px;font-size:10.5px;color:var(--text-secondary);border-bottom:1px solid var(--border-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.popover-meta[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%]{color:var(--text-muted)}.popover-list[_ngcontent-%COMP%]{flex:1;min-height:0;padding:4px}.row-item[_ngcontent-%COMP%]{width:100%;display:flex;align-items:center;gap:10px;padding:9px 10px;border:none;border-radius:7px;background:transparent;color:inherit;cursor:pointer;font-family:inherit;text-align:left;transition:background 80ms}.row-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.row-item.active[_ngcontent-%COMP%]{background:var(--accent-soft);color:var(--text-primary)}.row-item.active[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--accent)}.path-line[_ngcontent-%COMP%]{min-width:0}.path-line[_ngcontent-%COMP%] .path[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta[_ngcontent-%COMP%]{font-size:10.5px}.pill[_ngcontent-%COMP%]{font-size:10px;font-weight:600;padding:1px 7px;border-radius:999px;white-space:nowrap;flex-shrink:0}.pill.ok[_ngcontent-%COMP%]{color:var(--success);background:var(--success-soft)}.pill.warn[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft)}.pill.missing[_ngcontent-%COMP%]{color:var(--error);background:var(--error-soft)}.empty[_ngcontent-%COMP%]{text-align:center;color:var(--text-muted);font-size:12px;padding:18px 12px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1;min-width:0}.row[_ngcontent-%COMP%]{display:flex;align-items:center}.col[_ngcontent-%COMP%]{display:flex;flex-direction:column}.gap-2[_ngcontent-%COMP%]{gap:2px}.gap-6[_ngcontent-%COMP%]{gap:6px}.gap-8[_ngcontent-%COMP%]{gap:8px}.scroll-y[_ngcontent-%COMP%]{overflow-y:auto;overflow-x:hidden}"],changeDetection:0})};var K=class e{toggleSidebar=N();openPalette=N();theme=v($);effective=this.theme.effective;onToggleTheme(){this.theme.toggle()}onMenuClick(){this.toggleSidebar.emit()}onPalette(){this.openPalette.emit()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-top-bar"]],outputs:{toggleSidebar:"toggleSidebar",openPalette:"openPalette"},decls:13,vars:5,consts:[[1,"topbar"],["title","Toggle sidebar","aria-label","Toggle sidebar",1,"ghost","icon-btn",3,"click"],["name","menu",3,"size"],["aria-label","Open command palette",1,"palette-trigger",3,"click"],["name","search",3,"size"],[1,"grow"],["aria-label","Toggle theme",1,"ghost","icon-btn",3,"click","title"],[3,"name","size"]],template:function(t,i){t&1&&(a(0,"div",0)(1,"button",1),h("click",function(){return i.onMenuClick()}),p(2,"app-icon",2),r(),p(3,"app-project-picker"),a(4,"button",3),h("click",function(){return i.onPalette()}),p(5,"app-icon",4),a(6,"span"),l(7,"Search or jump to\u2026"),r(),a(8,"kbd"),l(9,"\u2318K"),r()(),p(10,"span",5),a(11,"button",6),h("click",function(){return i.onToggleTheme()}),p(12,"app-icon",7),r()()),t&2&&(o(2),f("size",16),o(3),f("size",13),o(6),f("title","Theme: "+i.effective()),o(),f("name",i.effective()==="dark"?"sun":"moon")("size",16))},dependencies:[D,q],styles:["[_nghost-%COMP%]{display:contents}.topbar[_ngcontent-%COMP%]{height:44px;flex-shrink:0;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid var(--border-subtle);background:var(--bg-canvas)}.ghost[_ngcontent-%COMP%]{background:transparent;border:1px solid transparent;color:var(--text-secondary);cursor:pointer}.ghost[_ngcontent-%COMP%]:hover{background:var(--bg-hover);color:var(--text-primary)}.icon-btn[_ngcontent-%COMP%]{padding:6px 9px;border-radius:5px;font-size:16px}.palette-trigger[_ngcontent-%COMP%]{flex:1;max-width:380px;height:30px;padding:0 11px;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:8px;cursor:text;color:var(--text-muted);font-size:12.5px;text-align:left;display:flex;align-items:center;gap:8px}.palette-trigger[_ngcontent-%COMP%]:hover{border-color:var(--border-strong);color:var(--text-secondary)}.palette-trigger[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted)}.palette-trigger[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{flex:1}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}.grow[_ngcontent-%COMP%]{flex:1}"],changeDetection:0})};var Ue=(e,n)=>n.id;function Qe(e,n){if(e&1){let t=k();d(0,"button",6),R("click",function(){let s=y(t).$implicit,_=m(2);return P(_.go(s.id))}),d(1,"span",7),l(2),c(),d(3,"span",8),l(4),c()()}if(e&2){let t=n.$implicit;o(2),b(t.label),o(2),b(t.sub)}}function Ye(e,n){if(e&1){let t=k();d(0,"div",1),R("click",function(s){y(t);let _=m();return P(_.onBackdrop(s))}),d(1,"div",2)(2,"div",3)(3,"span"),l(4,"Jump to\u2026"),c(),d(5,"kbd"),l(6,"esc"),c()(),d(7,"div",4),O(8,Qe,5,2,"button",5,Ue),c()()()}if(e&2){let t=m();o(8),E(t.items)}}var Je=[{id:"dashboard",label:"Dashboard",sub:"/dashboard"},{id:"graph",label:"Graph",sub:"/graph"},{id:"specs",label:"Specs",sub:"/specs"},{id:"drift",label:"Drift queue",sub:"/drift"},{id:"workflows",label:"Workflows",sub:"/workflows"},{id:"runs",label:"Runs",sub:"/runs"},{id:"chat",label:"Chat",sub:"/chat"},{id:"sessions",label:"Sessions",sub:"/sessions"},{id:"heatmap",label:"Heatmap",sub:"/heatmap"},{id:"costs",label:"Costs",sub:"/costs"},{id:"compare",label:"Compare projects",sub:"/compare"},{id:"tips",label:"Tips",sub:"/tips"},{id:"settings",label:"Settings",sub:"/settings"}],W=class e{open=S(!1);close=N();router=v(B);items=Je;go(n){this.router.navigate(["/"+n]),this.close.emit()}onBackdrop(n){n.target===n.currentTarget&&this.close.emit()}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-command-palette"]],inputs:{open:[1,"open"]},outputs:{close:"close"},decls:1,vars:1,consts:[[1,"backdrop"],[1,"backdrop",3,"click"],[1,"palette"],[1,"palette-header"],[1,"palette-list","scroll-y"],[1,"item"],[1,"item",3,"click"],[1,"label"],[1,"sub","mono"]],template:function(t,i){t&1&&g(0,Ye,10,0,"div",0),t&2&&u(i.open()?0:-1)},styles:["[_nghost-%COMP%]{display:contents}.backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:grid;place-items:start center;padding-top:12vh;z-index:100;animation:fadeIn .1s}.palette[_ngcontent-%COMP%]{width:560px;max-width:90vw;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-pop);overflow:hidden}.palette-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:12px 14px;border-bottom:1px solid var(--border-subtle);font-size:13px}.palette-list[_ngcontent-%COMP%]{max-height:380px;padding:6px}.item[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;width:100%;padding:8px 10px;background:transparent;border:none;border-radius:7px;cursor:pointer;color:var(--text-primary);font-family:inherit;font-size:13px;text-align:left}.item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.label[_ngcontent-%COMP%]{flex:1}.sub[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-muted)}kbd[_ngcontent-%COMP%]{font-family:var(--font-mono);font-size:10px;color:var(--text-muted);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:4px;padding:2px 6px}"],changeDetection:0})};var U=class e{_theme=v($);_destroyRef=v(ee);_router=v(B);sidebarCollapsed=T(typeof window<"u"&&window.innerWidth<1100);paletteOpen=T(!1);gChord={armed:!1,t:0};onGlobalKey(n){let t=n.metaKey||n.ctrlKey;if(t&&n.key.toLowerCase()==="k"){n.preventDefault(),this.paletteOpen.update(i=>!i);return}if(n.key==="Escape"){this.paletteOpen.set(!1);return}if(!t&&n.key.toLowerCase()==="g"&&!this.gChord.armed){let i=n.target;if(i&&/input|textarea/i.test(i.tagName))return;this.gChord.armed=!0,this.gChord.t=Date.now(),setTimeout(()=>{this.gChord.armed=!1},600);return}if(this.gChord.armed&&!t){let i=n.key.toLowerCase();i==="d"?this._router.navigate(["/dashboard"]):i==="g"?this._router.navigate(["/graph"]):i==="s"&&this._router.navigate(["/specs"]),this.gChord.armed=!1}}toggleSidebar(){this.sidebarCollapsed.update(n=>!n)}onOpenPalette(){this.paletteOpen.set(!0)}onClosePalette(){this.paletteOpen.set(!1)}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=x({type:e,selectors:[["app-root"]],hostBindings:function(t,i){t&1&&h("keydown",function(_){return i.onGlobalKey(_)},ie)},decls:8,vars:2,consts:[[1,"shell"],[3,"collapsed"],[1,"main"],[3,"toggleSidebar","openPalette"],[1,"page-frame"],[3,"close","open"]],template:function(t,i){t&1&&(a(0,"div",0),p(1,"app-sidebar",1),a(2,"div",2),p(3,"app-status-strip"),a(4,"app-top-bar",3),h("toggleSidebar",function(){return i.toggleSidebar()})("openPalette",function(){return i.onOpenPalette()}),r(),a(5,"div",4),p(6,"router-outlet"),r()(),a(7,"app-command-palette",5),h("close",function(){return i.onClosePalette()}),r()()),t&2&&(o(),f("collapsed",i.sidebarCollapsed()),o(6),f("open",i.paletteOpen()))},dependencies:[se,H,G,K,W],styles:["[_nghost-%COMP%]{display:block;height:100%}.shell[_ngcontent-%COMP%]{display:flex;height:100vh;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base)}.main[_ngcontent-%COMP%]{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}.page-frame[_ngcontent-%COMP%]{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--bg-canvas)}"],changeDetection:0})};le(U,ue).catch(e=>console.error(e));
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@charset "UTF-8";@layer properties;@layer theme,base,components,utilities;@layer theme{:root,:host{--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing: .25rem;--ease-out: cubic-bezier(0, 0, .2, 1);--ease-in-out: cubic-bezier(.4, 0, .2, 1);--default-transition-duration: .15s;--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);--default-font-family: var(--font-sans);--default-mono-font-family: var(--font-mono)}}@layer base{*,:after,:before,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings, normal);font-variation-settings:var(--default-font-variation-settings, normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings, normal);font-variation-settings:var(--default-mono-font-variation-settings, normal);font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;border-radius:0;background-color:transparent;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px){::placeholder{color:currentcolor}@supports (color: color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]),::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer utilities{.collapse{visibility:collapse}.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.table{display:table}.flex-shrink{flex-shrink:1}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.flex-wrap{flex-wrap:wrap}.gap-2{gap:calc(var(--spacing) * 2)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-7{gap:calc(var(--spacing) * 7)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-10{gap:calc(var(--spacing) * 10)}.gap-12{gap:calc(var(--spacing) * 12)}.gap-16{gap:calc(var(--spacing) * 16)}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.border{border-style:var(--tw-border-style);border-width:1px}.capitalize{text-transform:capitalize}.ring{--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function));transition-duration:var(--tw-duration, var(--default-transition-duration))}.ease-in-out{--tw-ease: var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease: var(--ease-out);transition-timing-function:var(--ease-out)}}:root{color-scheme:dark;--bg-canvas: #0E1014;--bg-canvas-2: #0B0D11;--bg-panel: #161A21;--bg-panel-2: #1A1F28;--bg-elevated: #20262F;--bg-hover: rgba(255,255,255,.04);--bg-active: rgba(255,255,255,.07);--border-subtle: rgba(255,255,255,.07);--border-strong: rgba(255,255,255,.12);--border-focus: #3B82F6;--text-primary: #E8EBF0;--text-secondary: #9AA3B2;--text-muted: #5C6573;--text-faint: #424B59;--accent: #3B82F6;--accent-strong: #2563EB;--accent-soft: rgba(59,130,246,.14);--accent-line: rgba(59,130,246,.35);--node-code: #A586F5;--node-spec: #5B93F2;--node-test: #46C26B;--node-route: #29D2BE;--node-code-soft: rgba(165,134,245,.14);--node-spec-soft: rgba(91,147,242,.14);--node-test-soft: rgba(70,194,107,.14);--node-route-soft: rgba(41,210,190,.14);--node-text: #ffffff;--dot-grid: rgba(255,255,255,.045);--success: #46C26B;--success-soft: rgba(70,194,107,.13);--warn: #E5A50A;--warn-soft: rgba(229,165,10,.14);--error: #F2555A;--error-soft: rgba(242,85,90,.14);--info: #58A6FF;--info-soft: rgba(88,166,255,.13);--font-ui: "Geist", system-ui, -apple-system, sans-serif;--font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;--fs-title: 22px;--fs-base: 13px;--fs-sm: 12px;--fs-xs: 11px;--fs-big: 28px;--r-sm: 5px;--r-md: 8px;--r-lg: 12px;--r-pill: 999px;--shadow-pop: 0 12px 32px -8px rgba(0,0,0,.6), 0 2px 8px rgba(0,0,0,.4);--shadow-panel: 0 1px 0 rgba(255,255,255,.02) inset;--sidebar-w: 232px;--sidebar-w-collapsed: 56px;--status-h: 30px}[data-theme=light]{color-scheme:light;--bg-canvas: #F4F6F8;--bg-canvas-2: #E9ECF1;--bg-panel: #FFFFFF;--bg-panel-2: #F8FAFC;--bg-elevated: #FFFFFF;--bg-hover: rgba(15,23,42,.045);--bg-active: rgba(15,23,42,.07);--border-subtle: rgba(15,23,42,.1);--border-strong: rgba(15,23,42,.18);--border-focus: #2563EB;--text-primary: #161B22;--text-secondary: #4A5566;--text-muted: #7B8696;--text-faint: #A9B2C0;--accent: #2563EB;--accent-strong: #2563EB;--accent-soft: rgba(37,99,235,.1);--accent-line: rgba(37,99,235,.3);--node-code: #7C56E0;--node-spec: #2F6FE0;--node-test: #1E9E4C;--node-route: #0E9C8E;--node-code-soft: rgba(124,86,224,.12);--node-spec-soft: rgba(47,111,224,.12);--node-test-soft: rgba(30,158,76,.12);--node-route-soft: rgba(14,156,142,.12);--node-text: #1A2230;--dot-grid: rgba(15,23,42,.07);--success: #1E9E4C;--success-soft: rgba(30,158,76,.12);--warn: #B27500;--warn-soft: rgba(178,117,0,.13);--error: #DC4A4F;--error-soft: rgba(220,74,79,.12);--info: #2563EB;--info-soft: rgba(37,99,235,.11);--shadow-pop: 0 12px 32px -10px rgba(15,23,42,.22), 0 2px 8px rgba(15,23,42,.1);--shadow-panel: 0 1px 0 rgba(15,23,42,.02) inset}*{box-sizing:border-box}html,body{margin:0;padding:0;height:100%;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base);line-height:1.45;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-feature-settings:"cv01","cv03","ss03";overflow:hidden}#root{height:100%}::selection{background:var(--accent-soft)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#ffffff14;border-radius:999px;border:2px solid transparent;background-clip:content-box}::-webkit-scrollbar-thumb:hover{background:#ffffff29;background-clip:content-box}.mono{font-family:var(--font-mono);font-feature-settings:"zero"}.tnum{font-variant-numeric:tabular-nums}.btn{font-family:var(--font-ui);font-size:var(--fs-base);font-weight:500;border:1px solid transparent;border-radius:var(--r-sm);padding:6px 12px;display:inline-flex;align-items:center;gap:7px;cursor:pointer;white-space:nowrap;transition:background .1s ease,border-color .1s ease,color .1s ease;-webkit-user-select:none;user-select:none}.btn svg{width:14px;height:14px;flex-shrink:0}.btn-primary{background:var(--accent-strong);color:#fff}.btn-primary:hover{background:var(--accent)}.btn-secondary{background:var(--bg-elevated);color:var(--text-primary);border-color:var(--border-subtle)}.btn-secondary:hover{background:#283039;border-color:var(--border-strong)}.btn-ghost{background:transparent;color:var(--text-secondary)}.btn-ghost:hover{background:var(--bg-hover);color:var(--text-primary)}.btn-destructive{background:var(--error-soft);color:var(--error);border-color:#f2555a4d}.btn-destructive:hover{background:#f2555a38}.btn-sm{padding:4px 9px;font-size:var(--fs-sm)}.btn-xs{padding:2px 7px;font-size:var(--fs-xs);border-radius:4px}.btn:disabled{opacity:.4;cursor:not-allowed}.pill{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-xs);font-weight:600;padding:2px 8px;border-radius:var(--r-pill);letter-spacing:.01em;white-space:nowrap;line-height:1.5}.pill svg{width:11px;height:11px}.pill-dot{width:6px;height:6px;border-radius:50%}.card{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.card-pad{padding:14px}.input{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:var(--r-sm);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base);padding:6px 10px;outline:none;transition:border-color .1s ease,box-shadow .1s ease}.input:focus{border-color:var(--border-focus);box-shadow:0 0 0 3px var(--accent-soft)}.input::placeholder{color:var(--text-muted)}.eyebrow{font-size:var(--fs-xs);font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted)}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.row{display:flex;align-items:center}.col{display:flex;flex-direction:column}.gap-2{gap:2px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.grow{flex:1}.muted{color:var(--text-muted)}.secondary{color:var(--text-secondary)}.tabular{font-variant-numeric:tabular-nums}.scroll-y{overflow-y:auto;overflow-x:hidden}@keyframes pulsePill{0%{box-shadow:0 0 0 0 currentColor}to{box-shadow:0 0 0 8px transparent}}@keyframes slideInRight{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes runningDash{to{stroke-dashoffset:-16}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton{0%{opacity:.5}50%{opacity:.9}to{opacity:.5}}.skel{background:var(--bg-elevated);border-radius:5px;animation:skeleton 1.4s ease-in-out infinite}@media(prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;transition-duration:.001ms!important}}@property --tw-rotate-x{syntax: "*"; inherits: false;}@property --tw-rotate-y{syntax: "*"; inherits: false;}@property --tw-rotate-z{syntax: "*"; inherits: false;}@property --tw-skew-x{syntax: "*"; inherits: false;}@property --tw-skew-y{syntax: "*"; inherits: false;}@property --tw-border-style{syntax: "*"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: "*"; inherits: false;}@property --tw-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: "*"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: "*"; inherits: false;}@property --tw-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: "*"; inherits: false;}@property --tw-inset-ring-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: "*"; inherits: false;}@property --tw-ring-offset-width{syntax: "<length>"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: "*"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: "*"; inherits: false; initial-value: 0 0 #0000;}@property --tw-blur{syntax: "*"; inherits: false;}@property --tw-brightness{syntax: "*"; inherits: false;}@property --tw-contrast{syntax: "*"; inherits: false;}@property --tw-grayscale{syntax: "*"; inherits: false;}@property --tw-hue-rotate{syntax: "*"; inherits: false;}@property --tw-invert{syntax: "*"; inherits: false;}@property --tw-opacity{syntax: "*"; inherits: false;}@property --tw-saturate{syntax: "*"; inherits: false;}@property --tw-sepia{syntax: "*"; inherits: false;}@property --tw-drop-shadow{syntax: "*"; inherits: false;}@property --tw-drop-shadow-color{syntax: "*"; inherits: false;}@property --tw-drop-shadow-alpha{syntax: "<percentage>"; inherits: false; initial-value: 100%;}@property --tw-drop-shadow-size{syntax: "*"; inherits: false;}@property --tw-ease{syntax: "*"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x: initial;--tw-rotate-y: initial;--tw-rotate-z: initial;--tw-skew-x: initial;--tw-skew-y: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-blur: initial;--tw-brightness: initial;--tw-contrast: initial;--tw-grayscale: initial;--tw-hue-rotate: initial;--tw-invert: initial;--tw-opacity: initial;--tw-saturate: initial;--tw-sepia: initial;--tw-drop-shadow: initial;--tw-drop-shadow-color: initial;--tw-drop-shadow-alpha: 100%;--tw-drop-shadow-size: initial;--tw-ease: initial}}}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
name: claude-design-implement
|
|
2
|
+
description: Import a Claude Design file (snapshot + tokens + source record), draft the spec, gate at review, write the spec — ready to hand off to /ss-implement.
|
|
3
|
+
tags: [spec, ui, claude-design, default]
|
|
4
|
+
requires: [specship, git]
|
|
5
|
+
|
|
6
|
+
# Worktree isolation: the spec draft and snapshot live in the user's
|
|
7
|
+
# working tree (not the worktree) so the artifacts survive the run,
|
|
8
|
+
# but the worktree gives the spec author a clean diff to review and
|
|
9
|
+
# means a rejected run leaves no half-written specs/<slug>.md.
|
|
10
|
+
worktree:
|
|
11
|
+
enabled: true
|
|
12
|
+
|
|
13
|
+
inputs:
|
|
14
|
+
- name: CONNECTOR_URL
|
|
15
|
+
description: The full Claude Design URL (https://claude.ai/design/p/<id>/?file=<name>.html)
|
|
16
|
+
required: true
|
|
17
|
+
- name: FILE_LABEL
|
|
18
|
+
description: Human label for the imported file (e.g. "Data Flow")
|
|
19
|
+
required: true
|
|
20
|
+
- name: SLUG
|
|
21
|
+
description: Kebab-case directory name under specs/ (e.g. "data-flow")
|
|
22
|
+
required: true
|
|
23
|
+
- name: OWNER
|
|
24
|
+
description: Spec owner — used in frontmatter when set
|
|
25
|
+
required: false
|
|
26
|
+
- name: PRIORITY
|
|
27
|
+
description: high / medium / low — used in frontmatter when set
|
|
28
|
+
required: false
|
|
29
|
+
|
|
30
|
+
systemPromptAppend: |
|
|
31
|
+
You are implementing a Claude Design import for SpecShip.
|
|
32
|
+
|
|
33
|
+
The fidelity principle: never paraphrase or summarise design content
|
|
34
|
+
when capturing it. The snapshot HTML and tokens.css are the
|
|
35
|
+
zero-loss reference layer; the spec captures contract only (behaviour,
|
|
36
|
+
accessibility, responsive, interaction states, data shape).
|
|
37
|
+
|
|
38
|
+
Use whichever Claude Design tooling is available (an MCP connector,
|
|
39
|
+
the figma-implement-design skill, or a direct fetch) to pull the
|
|
40
|
+
source file. Save it byte-for-byte to specs/$INPUT.SLUG/snapshot.html.
|
|
41
|
+
Never edit the snapshot during this workflow.
|
|
42
|
+
|
|
43
|
+
nodes:
|
|
44
|
+
- id: snapshot
|
|
45
|
+
kind: prompt
|
|
46
|
+
output_type: snapshot_summary
|
|
47
|
+
allowed_tools:
|
|
48
|
+
- Read
|
|
49
|
+
- Write
|
|
50
|
+
- Bash
|
|
51
|
+
- mcp__specship__specship_explore
|
|
52
|
+
- mcp__specship__specship_search
|
|
53
|
+
prompt: |
|
|
54
|
+
Source URL: $INPUT.CONNECTOR_URL
|
|
55
|
+
File label: $INPUT.FILE_LABEL
|
|
56
|
+
Slug: $INPUT.SLUG
|
|
57
|
+
|
|
58
|
+
Goal: snapshot the Claude Design source into specs/$INPUT.SLUG/
|
|
59
|
+
so the rest of the workflow has a zero-loss reference layer.
|
|
60
|
+
|
|
61
|
+
1. Create the directory `specs/$INPUT.SLUG/` if it doesn't exist.
|
|
62
|
+
|
|
63
|
+
2. Fetch the design content from $INPUT.CONNECTOR_URL. Try in
|
|
64
|
+
this order:
|
|
65
|
+
a. Any Claude Design MCP connector tool available in this
|
|
66
|
+
session (look for `mcp__*design*` or similar).
|
|
67
|
+
b. The `figma-implement-design` or `figma-use` skill if
|
|
68
|
+
loaded — Claude Design and Figma share a similar handoff
|
|
69
|
+
shape.
|
|
70
|
+
c. A direct `curl` of the URL, as a last resort.
|
|
71
|
+
|
|
72
|
+
Save the FULL rendered HTML byte-for-byte to
|
|
73
|
+
`specs/$INPUT.SLUG/snapshot.html`. Do NOT filter, summarise, or
|
|
74
|
+
re-format. If the design has linked CSS / asset files, save
|
|
75
|
+
them alongside.
|
|
76
|
+
|
|
77
|
+
3. Write `specs/$INPUT.SLUG/source.md` with the import audit
|
|
78
|
+
record:
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
# $INPUT.FILE_LABEL — Claude Design import
|
|
82
|
+
|
|
83
|
+
**Imported:** <today's date in YYYY-MM-DD>
|
|
84
|
+
**Connector URL:** $INPUT.CONNECTOR_URL
|
|
85
|
+
**Project ID:** <extracted from the URL — the segment after /p/>
|
|
86
|
+
**File:** $INPUT.FILE_LABEL
|
|
87
|
+
|
|
88
|
+
**Snapshot:** snapshot.html (byte-for-byte capture)
|
|
89
|
+
**Tokens:** tokens.css (extracted CSS custom properties)
|
|
90
|
+
|
|
91
|
+
**Original prompt:**
|
|
92
|
+
> Import this Claude Design project using the Claude Design connector:
|
|
93
|
+
> $INPUT.CONNECTOR_URL
|
|
94
|
+
> Implement: $INPUT.FILE_LABEL
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
4. Extract CSS custom properties + literal token-like values
|
|
98
|
+
(colors, spacing, font sizes, radii, transitions) from the
|
|
99
|
+
snapshot to `specs/$INPUT.SLUG/tokens.css`. Use
|
|
100
|
+
`specship_explore` first to find the project's existing token
|
|
101
|
+
system — if a value in the snapshot matches an existing
|
|
102
|
+
project token, map it by name instead of duplicating.
|
|
103
|
+
|
|
104
|
+
Output: a ≤250-word summary covering:
|
|
105
|
+
- Snapshot structure (top-level layout, key components).
|
|
106
|
+
- Token mapping (which match existing project tokens, which are
|
|
107
|
+
new and added to tokens.css).
|
|
108
|
+
- Any visible interaction or state cues in the CSS (`:hover`,
|
|
109
|
+
`:focus`, `:disabled`, `[aria-*]` selectors) the spec
|
|
110
|
+
author should be aware of.
|
|
111
|
+
|
|
112
|
+
- id: draft_spec
|
|
113
|
+
kind: prompt
|
|
114
|
+
depends_on: [snapshot]
|
|
115
|
+
output_type: spec_markdown
|
|
116
|
+
allowed_tools:
|
|
117
|
+
- Read
|
|
118
|
+
- mcp__specship__specship_explore
|
|
119
|
+
- mcp__specship__specship_search
|
|
120
|
+
- mcp__specship__specship_node
|
|
121
|
+
- mcp__specship__specship_spec
|
|
122
|
+
prompt: |
|
|
123
|
+
Use the spec-author skill (~/.claude/skills/spec-author/SKILL.md
|
|
124
|
+
and its references/) to draft a SpecShip-compatible spec for the
|
|
125
|
+
Claude Design import. Inputs available on disk:
|
|
126
|
+
|
|
127
|
+
- specs/$INPUT.SLUG/snapshot.html (visual + structural source)
|
|
128
|
+
- specs/$INPUT.SLUG/tokens.css (design tokens)
|
|
129
|
+
- specs/$INPUT.SLUG/source.md (audit record)
|
|
130
|
+
|
|
131
|
+
Spec scope: $INPUT.FILE_LABEL component(s).
|
|
132
|
+
Optional inputs: owner=$INPUT.OWNER priority=$INPUT.PRIORITY
|
|
133
|
+
|
|
134
|
+
Cover, as separate REQs:
|
|
135
|
+
- Behavioural contract (what the component renders, given what data).
|
|
136
|
+
- Each visible state (default, hover, focused, pressed, disabled,
|
|
137
|
+
loading, error, empty) — derive from the CSS, gap-fill the rest.
|
|
138
|
+
- Accessibility (keyboard nav, ARIA roles, focus order, contrast,
|
|
139
|
+
screen-reader behaviour).
|
|
140
|
+
- Responsive behaviour (breakpoints by name, not pixels).
|
|
141
|
+
- Data shape + failure-mode contracts.
|
|
142
|
+
- Performance contract (initial render budget, interaction
|
|
143
|
+
latency, if applicable).
|
|
144
|
+
|
|
145
|
+
DO NOT put exact hex colors, pixel values, font names, or animation
|
|
146
|
+
durations in the spec. Reference design tokens by name
|
|
147
|
+
(`MUST use the --error color token`). The values themselves live
|
|
148
|
+
in tokens.css.
|
|
149
|
+
|
|
150
|
+
Embed the import-source record in the spec's frontmatter so the
|
|
151
|
+
spec carries its provenance:
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
---
|
|
155
|
+
id: <SLUG-DOC>
|
|
156
|
+
title: <FILE_LABEL>
|
|
157
|
+
owner: <OWNER or "[needs review]">
|
|
158
|
+
priority: <PRIORITY or "[needs review]">
|
|
159
|
+
source: specs/<SLUG>/source.md
|
|
160
|
+
snapshot: specs/<SLUG>/snapshot.html
|
|
161
|
+
tokens: specs/<SLUG>/tokens.css
|
|
162
|
+
---
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Output: the full Markdown body of the proposed spec
|
|
166
|
+
(with frontmatter, embedded `<!-- id: -->` markers, RFC 2119
|
|
167
|
+
keywords, acceptance bullets with .A1/.A2 IDs). DO NOT write
|
|
168
|
+
it to disk yet — the next node is a review gate.
|
|
169
|
+
|
|
170
|
+
- id: gap_review
|
|
171
|
+
kind: approval
|
|
172
|
+
depends_on: [draft_spec]
|
|
173
|
+
message: |
|
|
174
|
+
Spec draft ready for $INPUT.FILE_LABEL.
|
|
175
|
+
|
|
176
|
+
Walk the [needs review] markers and gap-fill questions, then
|
|
177
|
+
approve to write the file. Reject with feedback to revise.
|
|
178
|
+
|
|
179
|
+
─────── DRAFT ───────
|
|
180
|
+
$draft_spec.output
|
|
181
|
+
capture_response: true
|
|
182
|
+
on_reject:
|
|
183
|
+
prompt: |
|
|
184
|
+
The draft was rejected with this feedback. Revise the spec
|
|
185
|
+
per the feedback; keep ALL existing REQ IDs stable so any
|
|
186
|
+
downstream tracking survives the rewrite.
|
|
187
|
+
|
|
188
|
+
Feedback:
|
|
189
|
+
$gap_review.output
|
|
190
|
+
|
|
191
|
+
Current draft:
|
|
192
|
+
$draft_spec.output
|
|
193
|
+
|
|
194
|
+
Output the revised draft.
|
|
195
|
+
max_attempts: 3
|
|
196
|
+
|
|
197
|
+
- id: write_spec
|
|
198
|
+
kind: prompt
|
|
199
|
+
depends_on: [gap_review]
|
|
200
|
+
output_type: file_path
|
|
201
|
+
allowed_tools:
|
|
202
|
+
- Write
|
|
203
|
+
- Read
|
|
204
|
+
- Bash
|
|
205
|
+
prompt: |
|
|
206
|
+
Write the approved spec to `specs/$INPUT.SLUG.md` using the
|
|
207
|
+
Write tool.
|
|
208
|
+
|
|
209
|
+
If `specs/$INPUT.SLUG.md` already exists (re-importing an
|
|
210
|
+
iteration), APPEND the new requirements to it instead of
|
|
211
|
+
overwriting; preserve all existing REQ IDs. Tell the user
|
|
212
|
+
explicitly what you did.
|
|
213
|
+
|
|
214
|
+
Approved draft:
|
|
215
|
+
$gap_review.output
|
|
216
|
+
|
|
217
|
+
Then run:
|
|
218
|
+
specship sync
|
|
219
|
+
|
|
220
|
+
Output: the relative path of the file written + the first REQ
|
|
221
|
+
ID (e.g. "REQ-DATA-FLOW-001") so the next step can hand it to
|
|
222
|
+
/ss-implement.
|
|
223
|
+
|
|
224
|
+
- id: handoff
|
|
225
|
+
kind: prompt
|
|
226
|
+
depends_on: [write_spec]
|
|
227
|
+
output_type: handoff_message
|
|
228
|
+
allowed_tools:
|
|
229
|
+
- Read
|
|
230
|
+
prompt: |
|
|
231
|
+
The spec is now indexed. Output a short hand-off message for the
|
|
232
|
+
user with EXACTLY these elements:
|
|
233
|
+
|
|
234
|
+
1. The path of the spec file: `specs/$INPUT.SLUG.md`.
|
|
235
|
+
2. The full list of REQ IDs the spec defines, one per line.
|
|
236
|
+
3. The reference files the implementation phase should read:
|
|
237
|
+
- specs/$INPUT.SLUG/snapshot.html
|
|
238
|
+
- specs/$INPUT.SLUG/tokens.css
|
|
239
|
+
- specs/$INPUT.SLUG/source.md
|
|
240
|
+
4. The exact next command:
|
|
241
|
+
/ss-implement <first REQ ID>
|
|
242
|
+
5. A one-line reminder that the implementation step should
|
|
243
|
+
load the snapshot for visual fidelity — the spec covers
|
|
244
|
+
contract only.
|
|
245
|
+
|
|
246
|
+
Keep the message ≤200 words. The user is about to switch from
|
|
247
|
+
this workflow to the implement workflow; this is the bridge.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
name: spec-author
|
|
2
|
+
description: Author a new spec. Draft → gap-fill review → quality review → final approval → write file.
|
|
3
|
+
tags: [spec, default]
|
|
4
|
+
requires: [specship, git]
|
|
5
|
+
|
|
6
|
+
# Worktree isolation isn't strictly needed for spec authoring (no code
|
|
7
|
+
# changes) — but enabling it keeps the artifact directory under the same
|
|
8
|
+
# umbrella the other spec workflows use, and a future expansion that adds
|
|
9
|
+
# example-code touches stays safe.
|
|
10
|
+
worktree:
|
|
11
|
+
enabled: true
|
|
12
|
+
|
|
13
|
+
inputs:
|
|
14
|
+
- name: DESCRIPTION
|
|
15
|
+
description: One-line description of the feature you want to spec
|
|
16
|
+
required: true
|
|
17
|
+
- name: PARENT_DOC
|
|
18
|
+
description: Optional spec ID of an existing doc to attach the new requirements under
|
|
19
|
+
required: false
|
|
20
|
+
- name: OWNER
|
|
21
|
+
description: Owner team or person (e.g. "security", "payments-team")
|
|
22
|
+
required: false
|
|
23
|
+
- name: PRIORITY
|
|
24
|
+
description: high / medium / low
|
|
25
|
+
required: false
|
|
26
|
+
|
|
27
|
+
systemPromptAppend: |
|
|
28
|
+
You are authoring a SpecShip-compatible Markdown spec. Use the
|
|
29
|
+
spec-author skill loop and references throughout this workflow.
|
|
30
|
+
The output of every node should be markdown that is ready for the
|
|
31
|
+
next stage — do NOT write the file until the `write_file` node.
|
|
32
|
+
|
|
33
|
+
nodes:
|
|
34
|
+
- id: ground
|
|
35
|
+
kind: prompt
|
|
36
|
+
output_type: code_grounding
|
|
37
|
+
allowed_tools:
|
|
38
|
+
- mcp__specship__specship_explore
|
|
39
|
+
- mcp__specship__specship_search
|
|
40
|
+
- mcp__specship__specship_files
|
|
41
|
+
- Read
|
|
42
|
+
prompt: |
|
|
43
|
+
Feature: $INPUT.DESCRIPTION
|
|
44
|
+
|
|
45
|
+
Walk the codebase to find where this feature would live:
|
|
46
|
+
|
|
47
|
+
1. Use specship_explore on terms drawn from the description to
|
|
48
|
+
surface relevant existing symbols.
|
|
49
|
+
2. Note any existing conventions, similar features, or shared
|
|
50
|
+
primitives the new spec should align with.
|
|
51
|
+
3. List candidate file paths + qualified symbol names that the
|
|
52
|
+
new implementation might touch — these become the `implementations:`
|
|
53
|
+
block of the spec.
|
|
54
|
+
|
|
55
|
+
If this is greenfield (no relevant existing code), say so explicitly
|
|
56
|
+
and propose a target directory under src/ where the implementation
|
|
57
|
+
will live.
|
|
58
|
+
|
|
59
|
+
Output: a ≤300-word grounding report — paths, conventions, and
|
|
60
|
+
candidate symbols. Do NOT write the spec yet.
|
|
61
|
+
|
|
62
|
+
- id: draft
|
|
63
|
+
kind: prompt
|
|
64
|
+
depends_on: [ground]
|
|
65
|
+
output_type: spec_draft
|
|
66
|
+
allowed_tools:
|
|
67
|
+
- mcp__specship__specship_spec
|
|
68
|
+
- mcp__specship__specship_explore
|
|
69
|
+
- mcp__specship__specship_node
|
|
70
|
+
- Read
|
|
71
|
+
prompt: |
|
|
72
|
+
Feature: $INPUT.DESCRIPTION
|
|
73
|
+
Optional parent doc: $INPUT.PARENT_DOC
|
|
74
|
+
Optional owner: $INPUT.OWNER
|
|
75
|
+
Optional priority: $INPUT.PRIORITY
|
|
76
|
+
|
|
77
|
+
Code grounding:
|
|
78
|
+
$ground.output
|
|
79
|
+
|
|
80
|
+
Produce a complete first-draft Markdown spec following the spec-author
|
|
81
|
+
skill's `references/format.md`:
|
|
82
|
+
|
|
83
|
+
- YAML frontmatter with id/title/owner/priority (use the inputs if
|
|
84
|
+
provided; mark as `[needs review]` if not).
|
|
85
|
+
- Embedded `<!-- id: -->` markers above every heading.
|
|
86
|
+
- RFC 2119 keyword (MUST / SHOULD / MAY) in each requirement title.
|
|
87
|
+
- One concern per requirement.
|
|
88
|
+
- `## Acceptance` section with bulleted criteria, each carrying its
|
|
89
|
+
own `.A<N>` ID. Cover both happy path and failure path.
|
|
90
|
+
- Optional `implementations:` block, populated from the grounding
|
|
91
|
+
report (or empty for greenfield).
|
|
92
|
+
- Wherever the description doesn't tell you something, insert a
|
|
93
|
+
`[needs user confirmation]` marker — DO NOT invent.
|
|
94
|
+
|
|
95
|
+
Output: the full spec markdown, ready for the gap-fill review.
|
|
96
|
+
|
|
97
|
+
- id: gap_review
|
|
98
|
+
kind: approval
|
|
99
|
+
depends_on: [draft]
|
|
100
|
+
message: |
|
|
101
|
+
Draft is ready. The gap-fill questions below identify areas the
|
|
102
|
+
description didn't cover. Approve with answers (e.g. "owner: security,
|
|
103
|
+
TTL: 1h, on non-existent email: 200 OK"), or reject with feedback to
|
|
104
|
+
revise.
|
|
105
|
+
|
|
106
|
+
Draft:
|
|
107
|
+
$draft.output
|
|
108
|
+
|
|
109
|
+
Gap-fill questions for THIS draft — walk references/gap-questions.md
|
|
110
|
+
and surface only the unanswered ones (max 5):
|
|
111
|
+
[the agent fills these in based on the draft above]
|
|
112
|
+
capture_response: true
|
|
113
|
+
on_reject:
|
|
114
|
+
prompt: |
|
|
115
|
+
The draft was rejected with this feedback. Revise the draft to
|
|
116
|
+
address it. Keep all existing IDs stable so any pre-existing links
|
|
117
|
+
survive.
|
|
118
|
+
|
|
119
|
+
Feedback:
|
|
120
|
+
$gap_review.output
|
|
121
|
+
max_attempts: 3
|
|
122
|
+
|
|
123
|
+
- id: incorporate
|
|
124
|
+
kind: prompt
|
|
125
|
+
depends_on: [gap_review]
|
|
126
|
+
output_type: spec_draft
|
|
127
|
+
allowed_tools:
|
|
128
|
+
- Read
|
|
129
|
+
prompt: |
|
|
130
|
+
Apply the gap-fill answers to the draft. Replace `[needs user
|
|
131
|
+
confirmation]` markers with the user's answers where given; leave
|
|
132
|
+
others as `[needs review]` if they explicitly skipped.
|
|
133
|
+
|
|
134
|
+
Draft:
|
|
135
|
+
$draft.output
|
|
136
|
+
|
|
137
|
+
Answers:
|
|
138
|
+
$gap_review.output
|
|
139
|
+
|
|
140
|
+
Output: the updated spec markdown.
|
|
141
|
+
|
|
142
|
+
- id: quality_review
|
|
143
|
+
kind: prompt
|
|
144
|
+
depends_on: [incorporate]
|
|
145
|
+
output_type: review_findings
|
|
146
|
+
allowed_tools:
|
|
147
|
+
- mcp__specship__specship_explore
|
|
148
|
+
- mcp__specship__specship_node
|
|
149
|
+
- mcp__specship__specship_search
|
|
150
|
+
- Read
|
|
151
|
+
prompt: |
|
|
152
|
+
Run the spec-author skill's `references/review-checklist.md` against
|
|
153
|
+
this draft and produce a structured findings list.
|
|
154
|
+
|
|
155
|
+
Updated draft:
|
|
156
|
+
$incorporate.output
|
|
157
|
+
|
|
158
|
+
Group findings into STRUCTURAL (blocks the file write), QUALITY (block
|
|
159
|
+
on critical, warn on minor), HYGIENE (warn only). For each, give:
|
|
160
|
+
line number, what's wrong, suggested fix. Don't be polite — sharp
|
|
161
|
+
signal is more useful than soft language.
|
|
162
|
+
|
|
163
|
+
If any STRUCTURAL findings exist, propose a corrected version of the
|
|
164
|
+
affected sections inline.
|
|
165
|
+
|
|
166
|
+
- id: finalize
|
|
167
|
+
kind: approval
|
|
168
|
+
depends_on: [quality_review]
|
|
169
|
+
message: |
|
|
170
|
+
Quality review complete. Approve to write the spec file, or reject to
|
|
171
|
+
revise further.
|
|
172
|
+
|
|
173
|
+
Review:
|
|
174
|
+
$quality_review.output
|
|
175
|
+
|
|
176
|
+
Final draft:
|
|
177
|
+
$incorporate.output
|
|
178
|
+
capture_response: true
|
|
179
|
+
on_reject:
|
|
180
|
+
prompt: |
|
|
181
|
+
Final approval was rejected. Revise the draft per the feedback,
|
|
182
|
+
re-run the quality review pass, and produce a new draft.
|
|
183
|
+
|
|
184
|
+
Feedback:
|
|
185
|
+
$finalize.output
|
|
186
|
+
|
|
187
|
+
Current draft:
|
|
188
|
+
$incorporate.output
|
|
189
|
+
max_attempts: 2
|
|
190
|
+
|
|
191
|
+
- id: write_file
|
|
192
|
+
kind: prompt
|
|
193
|
+
depends_on: [finalize]
|
|
194
|
+
output_type: file_path
|
|
195
|
+
allowed_tools:
|
|
196
|
+
- Write
|
|
197
|
+
- Read
|
|
198
|
+
- Bash
|
|
199
|
+
prompt: |
|
|
200
|
+
Write the approved spec to disk.
|
|
201
|
+
|
|
202
|
+
Final draft:
|
|
203
|
+
$incorporate.output
|
|
204
|
+
|
|
205
|
+
Use the `Write` tool to create `specs/<slug>.md` at the project root,
|
|
206
|
+
where `<slug>` is derived from the feature name (kebab-case, no date
|
|
207
|
+
prefix). If a file with that name already exists, APPEND the new
|
|
208
|
+
requirements to it (preserving any pre-existing content) instead of
|
|
209
|
+
overwriting; the user will resolve the merge in review.
|
|
210
|
+
|
|
211
|
+
After writing:
|
|
212
|
+
- Run `specship sync` to index the new spec.
|
|
213
|
+
- Output the relative path of the file written + a one-line note
|
|
214
|
+
about what to do next (typically: `/ss-implement <REQ-ID>`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/workflows/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EACL,kBAAkB,EAClB,OAAO,EAOR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,iBAAiB,EAGlB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/workflows/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EACL,kBAAkB,EAClB,OAAO,EAOR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,iBAAiB,EAGlB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EACL,UAAU,EAIX,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,uBAAuB;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,WAAW,CAAC;IACjB,sCAAsC;IACtC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAClC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,OAAO,CAAmC;gBAEtC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB;IAgB3D,KAAK,CACT,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,aAAa,CAAC;IA8EzB;;OAEG;IACG,MAAM,CACV,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,aAAa,CAAC;IAoCzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAA4B,GAAG,IAAI;IA8BjE;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAuC9C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;YA6B9B,cAAc;YA0Id,YAAY;IA2B1B,OAAO,CAAC,YAAY;IAuBpB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;IAiDvB,OAAO,CAAC,uBAAuB;YAajB,QAAQ;YA4CR,aAAa;IAyB3B,OAAO,CAAC,KAAK;CA0Bd;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CA6BnD"}
|
|
@@ -55,6 +55,7 @@ const fs = __importStar(require("fs"));
|
|
|
55
55
|
const path = __importStar(require("path"));
|
|
56
56
|
const os = __importStar(require("os"));
|
|
57
57
|
const crypto_1 = require("crypto");
|
|
58
|
+
const directory_1 = require("../directory");
|
|
58
59
|
const condition_evaluator_1 = require("./condition-evaluator");
|
|
59
60
|
const prompt_1 = require("./runners/prompt");
|
|
60
61
|
const bash_1 = require("./runners/bash");
|
|
@@ -124,7 +125,7 @@ class WorkflowExecutor {
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
// Set up artifacts + logs dirs.
|
|
127
|
-
const specshipRoot =
|
|
128
|
+
const specshipRoot = (0, directory_1.getSpecShipDir)(opts.projectRoot);
|
|
128
129
|
const artifactsDir = path.join(specshipRoot, 'artifacts', 'runs', runId, 'nodes');
|
|
129
130
|
const logsDir = path.join(specshipRoot, 'logs');
|
|
130
131
|
try {
|
|
@@ -168,8 +169,8 @@ class WorkflowExecutor {
|
|
|
168
169
|
? this.specQueries.getIsolationEnvById(existing.isolationEnvId)?.workingPath ??
|
|
169
170
|
opts.projectRoot
|
|
170
171
|
: opts.projectRoot;
|
|
171
|
-
const artifactsDir = path.join(opts.projectRoot, '
|
|
172
|
-
const logsDir = path.join(opts.projectRoot, '
|
|
172
|
+
const artifactsDir = path.join((0, directory_1.getSpecShipDir)(opts.projectRoot), 'artifacts', 'runs', runId, 'nodes');
|
|
173
|
+
const logsDir = path.join((0, directory_1.getSpecShipDir)(opts.projectRoot), 'logs');
|
|
173
174
|
const now = Date.now();
|
|
174
175
|
const refreshed = {
|
|
175
176
|
...existing,
|