@selvakumaresra/specship 0.3.0 → 0.4.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 (69) hide show
  1. package/commands/ss-design-implement.md +5 -0
  2. package/commands/ss-design-loop.md +125 -0
  3. package/dist/bin/specship.js +66 -0
  4. package/dist/bin/specship.js.map +1 -1
  5. package/dist/designer/artifact-store.js +54 -0
  6. package/dist/designer/browser.js +141 -0
  7. package/dist/designer/cdp-ensure.js +60 -0
  8. package/dist/designer/cdp-env.js +18 -0
  9. package/dist/designer/cdp-trace.js +599 -0
  10. package/dist/designer/cross-platform.js +74 -0
  11. package/dist/designer/designer-controller.js +1413 -0
  12. package/dist/designer/file-panel.js +39 -0
  13. package/dist/designer/interstitials.js +97 -0
  14. package/dist/designer/oopif-reader.js +176 -0
  15. package/dist/designer/package-meta.js +18 -0
  16. package/dist/designer/preview-host.js +50 -0
  17. package/dist/designer/repo-root.js +31 -0
  18. package/dist/designer/run-state.js +353 -0
  19. package/dist/designer/session-store.js +59 -0
  20. package/dist/designer/ui-anchors.js +651 -0
  21. package/dist/installer/index.d.ts +5 -0
  22. package/dist/installer/index.d.ts.map +1 -1
  23. package/dist/installer/index.js +3 -2
  24. package/dist/installer/index.js.map +1 -1
  25. package/dist/installer/instructions-template.d.ts +17 -0
  26. package/dist/installer/instructions-template.d.ts.map +1 -1
  27. package/dist/installer/instructions-template.js +31 -1
  28. package/dist/installer/instructions-template.js.map +1 -1
  29. package/dist/installer/targets/claude.d.ts +19 -0
  30. package/dist/installer/targets/claude.d.ts.map +1 -1
  31. package/dist/installer/targets/claude.js +98 -1
  32. package/dist/installer/targets/claude.js.map +1 -1
  33. package/dist/installer/targets/shared.d.ts +14 -0
  34. package/dist/installer/targets/shared.d.ts.map +1 -1
  35. package/dist/installer/targets/shared.js +49 -0
  36. package/dist/installer/targets/shared.js.map +1 -1
  37. package/dist/installer/targets/types.d.ts +8 -0
  38. package/dist/installer/targets/types.d.ts.map +1 -1
  39. package/dist/mcp/designer-tools.d.ts +33 -0
  40. package/dist/mcp/designer-tools.d.ts.map +1 -0
  41. package/dist/mcp/designer-tools.js +313 -0
  42. package/dist/mcp/designer-tools.js.map +1 -0
  43. package/dist/mcp/tools.d.ts.map +1 -1
  44. package/dist/mcp/tools.js +22 -1
  45. package/dist/mcp/tools.js.map +1 -1
  46. package/dist/web/{chunk-JT7P3DEK.js → chunk-2YUJNZ2Y.js} +3 -3
  47. package/dist/web/{chunk-JN6W7HCN.js → chunk-45QHGCB4.js} +1 -1
  48. package/dist/web/{chunk-RAAMPHPJ.js → chunk-A5R3MJMO.js} +1 -1
  49. package/dist/web/{chunk-2DHIGIOI.js → chunk-ASZ77FMZ.js} +1 -1
  50. package/dist/web/{chunk-TWXZK6XM.js → chunk-B3YPFY6A.js} +1 -1
  51. package/dist/web/chunk-D5OCNEJA.js +2 -0
  52. package/dist/web/{chunk-3SEJX2BK.js → chunk-FHZHD2ZG.js} +1 -1
  53. package/dist/web/chunk-GR72OOCN.js +1 -0
  54. package/dist/web/{chunk-DA6SNNAF.js → chunk-GWPVKJIY.js} +1 -1
  55. package/dist/web/{chunk-YAWCRPHV.js → chunk-NZEZCT65.js} +1 -1
  56. package/dist/web/{chunk-BCZM5AXU.js → chunk-UBOZGQNK.js} +1 -1
  57. package/dist/web/{chunk-BPECIDVO.js → chunk-WCKHQIYN.js} +1 -1
  58. package/dist/web/{chunk-JFYVCXK3.js → chunk-WLIMNDS3.js} +1 -1
  59. package/dist/web/{chunk-LV4G6QFG.js → chunk-YAMRN47K.js} +1 -1
  60. package/dist/web/index.html +1 -1
  61. package/dist/web/main-R53HA54V.js +1 -0
  62. package/dist/web/sw.js +69 -0
  63. package/dist/workflows/defaults/claude-design-implement.yaml +138 -49
  64. package/hooks/hooks.json +11 -0
  65. package/package.json +7 -3
  66. package/selectors.json +41 -0
  67. package/dist/web/chunk-2OKMB4KX.js +0 -2
  68. package/dist/web/chunk-4N5DWG46.js +0 -1
  69. package/dist/web/main-WVI3YTDU.js +0 -1
@@ -1,6 +1,6 @@
1
- import{a as te}from"./chunk-G7VZT5KB.js";import{a as ne}from"./chunk-EMGMOEVR.js";import{a as ie}from"./chunk-X2HTISHL.js";import{a as ee}from"./chunk-R5W2MDZN.js";import{a as Y}from"./chunk-WDU3WICG.js";import{a as F,b as Z}from"./chunk-HZA6NEAB.js";import{b as W}from"./chunk-4N5DWG46.js";import{c as B}from"./chunk-SHPTC4RL.js";import{a as J}from"./chunk-7RNS77UP.js";import{a as X}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as y,I as M,Ia as x,Ka as s,M as f,N as C,Oa as H,Pa as Q,Qa as U,R as G,T as S,Ta as $,Ua as R,Va as d,W as _,Wa as g,Xa as b,aa as z,ea as o,ka as k,lb as h,ra as m,sa as u,va as I,wa as N,xa as c,ya as r,yb as K,za as l,zb as E}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var V=null,ue="self.onmessage = () => {};";function oe(){return V||(typeof window<"u"&&!window.MonacoEnvironment&&(window.MonacoEnvironment={getWorker:(i,t)=>{let e=new Blob([ue],{type:"text/javascript"}),n=URL.createObjectURL(e);return new Worker(n,{name:t||"monaco-noop"})}}),V=import("./chunk-FMV5PXRC.js"),V)}var re=!1;function ae(i){re||(re=!0,ge(i))}function le(i,t){let e=[],n=t.getValue().split(`
2
- `),a=null,v=new Map,P=/<!--\s*id\s*:\s*([^\s-][^\s]*)\s*-->/,me=/^#{1,6}\s+/;for(let O=0;O<n.length;O++){let T=n[O]??"",D=O+1,j=T.match(P);if(j&&j[1]){a!==null&&e.push({severity:i.MarkerSeverity.Warning,message:`Stranded <!-- id: ${a.id} -->: no heading follows on line ${a.line+1}.`,startLineNumber:a.line+1,startColumn:1,endLineNumber:a.line+1,endColumn:(n[a.line]??"").length+1,code:"spec_stranded_id"});let w=j[1];a={id:w,line:O};let q=v.get(w);q!==void 0?e.push({severity:i.MarkerSeverity.Warning,message:`Duplicate spec ID "${w}" \u2014 first seen on line ${q+1}. The second occurrence will be silently lost by the parser.`,startLineNumber:D,startColumn:T.indexOf(w)+1,endLineNumber:D,endColumn:T.indexOf(w)+w.length+1,code:"spec_duplicate_id"}):v.set(w,O);continue}me.test(T)&&(a===null?e.push({severity:i.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:D,startColumn:1,endLineNumber:D,endColumn:T.length+1,code:"spec_missing_id"}):a=null)}i.editor.setModelMarkers(t,"specship-spec",e)}function ge(i){i.languages.registerCompletionItemProvider("markdown",{provideCompletionItems:(t,e)=>{let n=t.getWordUntilPosition(e),a={startLineNumber:e.lineNumber,endLineNumber:e.lineNumber,startColumn:n.startColumn,endColumn:n.endColumn},v=i.languages.CompletionItemKind,P=i.languages.CompletionItemInsertTextRule;return{suggestions:[{label:"req",kind:v.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(`
1
+ import{a as ne}from"./chunk-G7VZT5KB.js";import{a as ie}from"./chunk-EMGMOEVR.js";import{a as oe}from"./chunk-X2HTISHL.js";import{a as te}from"./chunk-R5W2MDZN.js";import{a as Z}from"./chunk-WDU3WICG.js";import{a as F,b as ee}from"./chunk-HZA6NEAB.js";import{a as Y,c as W}from"./chunk-GR72OOCN.js";import{c as B}from"./chunk-SHPTC4RL.js";import{a as J}from"./chunk-7RNS77UP.js";import{a as X}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as w,I as y,Ia as x,Ka as s,M as f,N as h,Oa as H,Pa as Q,Qa as U,R as G,T as S,Ta as $,Ua as R,Va as d,W as _,Wa as g,Xa as b,aa as z,ea as o,ka as k,lb as C,ra as m,sa as u,va as I,wa as N,xa as c,ya as r,yb as K,za as l,zb as E}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var V=null,ge="self.onmessage = () => {};";function re(){return V||(typeof window<"u"&&!window.MonacoEnvironment&&(window.MonacoEnvironment={getWorker:(i,t)=>{let e=new Blob([ge],{type:"text/javascript"}),n=URL.createObjectURL(e);return new Worker(n,{name:t||"monaco-noop"})}}),V=import("./chunk-FMV5PXRC.js"),V)}var ae=!1;function le(i){ae||(ae=!0,_e(i))}function de(i,t){let e=[],n=t.getValue().split(`
2
+ `),a=null,v=new Map,P=/<!--\s*id\s*:\s*([^\s-][^\s]*)\s*-->/,ue=/^#{1,6}\s+/;for(let O=0;O<n.length;O++){let T=n[O]??"",D=O+1,j=T.match(P);if(j&&j[1]){a!==null&&e.push({severity:i.MarkerSeverity.Warning,message:`Stranded <!-- id: ${a.id} -->: no heading follows on line ${a.line+1}.`,startLineNumber:a.line+1,startColumn:1,endLineNumber:a.line+1,endColumn:(n[a.line]??"").length+1,code:"spec_stranded_id"});let M=j[1];a={id:M,line:O};let q=v.get(M);q!==void 0?e.push({severity:i.MarkerSeverity.Warning,message:`Duplicate spec ID "${M}" \u2014 first seen on line ${q+1}. The second occurrence will be silently lost by the parser.`,startLineNumber:D,startColumn:T.indexOf(M)+1,endLineNumber:D,endColumn:T.indexOf(M)+M.length+1,code:"spec_duplicate_id"}):v.set(M,O);continue}ue.test(T)&&(a===null?e.push({severity:i.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:D,startColumn:1,endLineNumber:D,endColumn:T.length+1,code:"spec_missing_id"}):a=null)}i.editor.setModelMarkers(t,"specship-spec",e)}function _e(i){i.languages.registerCompletionItemProvider("markdown",{provideCompletionItems:(t,e)=>{let n=t.getWordUntilPosition(e),a={startLineNumber:e.lineNumber,endLineNumber:e.lineNumber,startColumn:n.startColumn,endColumn:n.endColumn},v=i.languages.CompletionItemKind,P=i.languages.CompletionItemInsertTextRule;return{suggestions:[{label:"req",kind:v.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
3
  `),insertTextRules:P.InsertAsSnippet,documentation:"Insert a full requirement (heading + acceptance) with embedded IDs.",detail:"SpecShip \xB7 requirement",range:a},{label:"doc",kind:v.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
4
  `),insertTextRules:P.InsertAsSnippet,documentation:"Insert a new spec document with frontmatter.",detail:"SpecShip \xB7 document",range:a},{label:"accept",kind:v.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
5
  `),insertTextRules:P.InsertAsSnippet,documentation:"Insert an Acceptance section with two ID-d bullets.",detail:"SpecShip \xB7 acceptance",range:a},{label:"impl",kind:v.Snippet,insertText:["implementations:"," - ${1:src/path/to/file.ts}:${2:QualifiedSymbol}","$0"].join(`
6
- `),insertTextRules:P.InsertAsSnippet,documentation:"Insert an implementations block linking the spec to code.",detail:"SpecShip \xB7 implementations",range:a}]}},triggerCharacters:["r","d","a","i"]})}var _e=["host"];function ve(i,t){if(i&1&&(r(0,"span",5),d(1),l()),i&2){let e=s();c("title",e.path),o(),g(e.path)}}function xe(i,t){i&1&&(r(0,"div",15),d(1,"Loading editor\u2026"),l())}var L=class i{sanitizer=M(K);destroyRef=M(G);value="";path="";valueChange=new S;validationChange=new S;save=new S;cancel=new S;hostRef;loading=_(!0);currentValue=_("");errorCount=_(0);warningCount=_(0);dirty=_(!1);previewHtml=h(()=>this.sanitizer.bypassSecurityTrustHtml(te(this.currentValue()||"")));tokenCount=h(()=>Math.max(1,Math.round((this.currentValue()||"").length/4)));statusLabel=h(()=>{let t=this.errorCount(),e=this.warningCount();return t>0?`${t} error${t===1?"":"s"}`:e>0?`${e} warning${e===1?"":"s"}`:"clean"});statusKind=h(()=>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 oe();this.monaco=t,ae(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(a=>a.severity===this.monaco.MarkerSeverity.Error).length,n=t.filter(a=>a.severity===this.monaco.MarkerSeverity.Warning).length;this.errorCount.set(e),this.warningCount.set(n),this.validationChange.emit({errors:e,warnings:n})}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||i)};static \u0275cmp=k({type:i,selectors:[["app-spec-editor"]],viewQuery:function(e,n){if(e&1&&H(_e,7),e&2){let a;Q(a=U())&&(n.hostRef=a.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,n){e&1&&(r(0,"div",1)(1,"div",2),p(2,"app-icon",3),r(3,"span",4),d(4,"Spec editor"),l(),m(5,ve,2,2,"span",5),p(6,"span",6),r(7,"span",7),p(8,"span",8),d(9),l(),r(10,"span",9),d(11),l(),r(12,"button",10),x("click",function(){return n.onCancel()}),d(13," Cancel "),l(),r(14,"button",11),x("click",function(){return n.onSave()}),p(15,"app-icon",12),d(16," Save "),l()(),r(17,"div",13)(18,"div",14),m(19,xe,2,0,"div",15),p(20,"div",16,0),l(),p(22,"div",17),l()()),e&2&&(o(2),c("size",14),o(3),u(n.path?5:-1),o(2),R("ok",n.statusKind()==="ok")("warn",n.statusKind()==="warn")("error",n.statusKind()==="error"),o(2),b(" ",n.statusLabel()," "),o(),c("title","~"+n.tokenCount()+" tokens (rough estimate)"),o(),b(" ~",n.tokenCount(),"t "),o(3),c("disabled",!n.dirty()||n.errorCount()>0)("title",n.errorCount()>0?"Fix errors before saving":n.dirty()?"Save changes":"No changes to save"),o(),c("size",13),o(4),u(n.loading()?19:-1),o(3),c("innerHTML",n.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 fe(i,t){i&1&&(r(0,"div",14),d(1),l()),i&2&&(o(),g(t))}function Ce(i,t){if(i&1){let e=y();r(0,"div",0),x("click",function(){f(e);let a=s();return C(a.onBackdropClick())}),l(),r(1,"div",1)(2,"header",2)(3,"div",3)(4,"div",4),d(5,"Draft a new spec with Claude"),l(),r(6,"div",5),d(7,"Describe the feature in one sentence. Claude takes it from there."),l()(),r(8,"button",6),x("click",function(){f(e);let a=s();return C(a.onCloseClick())}),p(9,"app-icon",7),l()(),r(10,"div",8)(11,"label",9),d(12,"Feature description"),l(),r(13,"textarea",10),x("input",function(a){f(e);let v=s();return C(v.onDescriptionInput(a))}),l(),r(14,"div",11),d(15,"This will run in Claude Code:"),l(),r(16,"pre",12),d(17),l()(),r(18,"footer",13),m(19,fe,2,1,"div",14),p(20,"span",15),r(21,"button",16),x("click",function(){f(e);let a=s();return C(a.onCopyToClipboard())}),p(22,"app-icon",17),d(23," Copy prompt "),l(),r(24,"button",18),x("click",function(){f(e);let a=s();return C(a.onOpenInClaude())}),p(25,"app-icon",19),d(26," Open in Claude Code "),l()()()}if(i&2){let e,n=s();o(9),c("size",16),o(4),c("value",n.description()),o(4),g(n.slashCommand()),o(2),u((e=n.toast())?19:-1,e),o(2),c("disabled",!n.canSubmit()),o(),c("size",13),o(2),c("disabled",!n.canSubmit()),o(),c("size",13)}}var A=class i{open=!1;close=new S;description=_("");toast=_(null);slashCommand=h(()=>{let t=this.description().trim();return t?`/ss-spec-author "${t.replace(/"/g,'\\"')}"`:"/ss-spec-author"});canSubmit=h(()=>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||i)};static \u0275cmp=k({type:i,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,n){e&1&&m(0,Ce,27,8),e&2&&u(n.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=(i,t)=>t.path,pe=(i,t)=>t.id;function be(i,t){i&1&&p(0,"app-pick-project-empty",0)}function ye(i,t){i&1&&p(0,"app-empty",9)}function we(i,t){if(i&1&&(r(0,"span",18),d(1),l()),i&2){let e=s().$implicit,n=s(2);o(),b(" ",n.driftCountForGroup(e)," ")}}function Me(i,t){if(i&1){let e=y();r(0,"div",21),x("click",function(){let a=f(e).$implicit,v=s(4);return C(v.select(a.id))}),p(1,"span",22),r(2,"div",23)(3,"div",24),d(4),l(),r(5,"div",25),d(6),l()()()}if(i&2){let e=t.$implicit,n=s(4);R("selected",n.sel()===e.id),o(),$("background",n.stateColorFor(e.kind)),o(2),$("color",n.sel()===e.id?"var(--accent)":"var(--text-primary)"),o(),g(e.id),o(2),g(e.title)}}function Se(i,t){if(i&1&&(r(0,"div",19),I(1,Me,7,8,"div",20,pe),l()),i&2){let e=s().$implicit;o(),N(e.specs)}}function Pe(i,t){if(i&1){let e=y();r(0,"div",14),x("click",function(){let a=f(e).$implicit,v=s(2);return C(v.toggleGroup(a.path))}),p(1,"app-icon",15)(2,"app-icon",16),r(3,"span",17),d(4),l(),m(5,we,2,1,"span",18),l(),m(6,Se,3,0,"div",19)}if(i&2){let e=t.$implicit,n=s(2);o(),c("name",n.isGroupOpen(e.path)?"chevronDown":"chevronRight")("size",12),o(),c("size",13),o(2),g(e.title),o(),u(n.driftCountForGroup(e)>0?5:-1),o(),u(n.isGroupOpen(e.path)?6:-1)}}function Oe(i,t){if(i&1&&(r(0,"div",26),d(1),l()),i&2){let e=s();o(),b("Loading source for ",e.id,"\u2026")}}function ke(i,t){if(i&1){let e=y();r(0,"app-spec-editor",30),x("valueChange",function(a){f(e);let v=s(4);return C(v.onEditorValueChange(a))})("save",function(){f(e);let a=s(4);return C(a.onEditorSave())})("cancel",function(){f(e);let a=s(4);return C(a.onEditorCancel())}),l()}if(i&2){let e=s(),n=s(3);c("value",n.editingSource())("path",e.sourcePath)}}function Ee(i,t){i&1&&(r(0,"div",28),d(1),l()),i&2&&(o(),g(t))}function Te(i,t){i&1&&(r(0,"div",29),d(1,"Saving\u2026"),l())}function De(i,t){if(i&1&&(m(0,Oe,2,1,"div",26)(1,ke,1,2,"app-spec-editor",27),m(2,Ee,2,1,"div",28),m(3,Te,2,0,"div",29)),i&2){let e,n=s(3);u(n.editingSource()===null?0:1),o(2),u((e=n.saveError())?2:-1,e),o(),u(n.saving()?3:-1)}}function ze(i,t){if(i&1&&m(0,De,4,3),i&2){let e,n=s(2);u((e=n.selectedSpec())?0:-1,e)}}function Ie(i,t){if(i&1&&(r(0,"app-pill"),d(1),l()),i&2){let e=s();o(),g(e.priority)}}function Ne(i,t){if(i&1&&(r(0,"div",37)(1,"div",38),d(2,"Owner"),l(),r(3,"div",39),d(4),l()()),i&2){let e=s();o(4),g(e.owner)}}function $e(i,t){i&1&&p(0,"div",42)}function Re(i,t){if(i&1&&(r(0,"app-pill",56),d(1),l()),i&2){let e=s().$implicit;o(),b("",e.driftAxis," drift")}}function Ve(i,t){if(i&1&&(r(0,"div",55),p(1,"app-state-pill",34),m(2,Re,2,1,"app-pill",56),r(3,"span",57),d(4),l(),r(5,"app-pill"),d(6),l(),r(7,"button",58),p(8,"app-icon",51),d(9," Reveal "),l()()),i&2){let e=t.$implicit,n=t.$index;$("border-top",n>0?"1px solid var(--border-subtle)":"none"),o(),c("state",e.state),o(),u(e.driftAxis?2:-1),o(2),g(e.targetQualifiedName),o(2),g(e.provenance),o(2),c("size",12)}}function Le(i,t){if(i&1&&(r(0,"div",43),I(1,Ve,10,7,"div",54,pe),l()),i&2){let e=s(3);o(),N(e.selectedLinks())}}function Ae(i,t){i&1&&(r(0,"div",44),p(1,"app-icon",59),r(2,"div",60),d(3," Orphaned \u2014 no code implements this requirement yet "),l()()),i&2&&(o(),c("size",16))}function je(i,t){i&1&&(r(0,"div",53),d(1),l()),i&2&&(o(),g(t))}function We(i,t){if(i&1){let e=y();r(0,"div",11)(1,"div",31)(2,"span",32),d(3),l(),p(4,"app-copy-btn",33)(5,"div",6)(6,"app-state-pill",34),m(7,Ie,2,1,"app-pill"),l(),r(8,"h1",35),d(9),l(),r(10,"div",36)(11,"div",37)(12,"div",38),d(13,"Kind"),l(),r(14,"div",39),d(15),l()(),m(16,Ne,5,1,"div",37),r(17,"div",37)(18,"div",38),d(19,"Doc"),l(),r(20,"div",39),d(21),l()(),r(22,"div",37)(23,"div",38),d(24,"Siblings"),l(),r(25,"div",39),d(26),l()(),r(27,"div",37)(28,"div",38),d(29,"Links"),l(),r(30,"div",39),d(31),l()()(),r(32,"div",40),d(33,"Requirement"),l(),p(34,"div",41),r(35,"div",40),d(36,"Linked code"),l(),m(37,$e,1,0,"div",42)(38,Le,3,0,"div",43)(39,Ae,4,1,"div",44),r(40,"div",45)(41,"button",46),p(42,"app-icon",47),d(43," Implement "),l(),r(44,"button",48),p(45,"app-icon",49),d(46," Verify "),l(),r(47,"button",50),x("click",function(){f(e);let a=s(2);return C(a.onEditClick())}),p(48,"app-icon",51),d(49," Edit spec "),l(),r(50,"button",50),x("click",function(){let a=f(e),v=s(2);return C(v.goToGraph(a.id))}),p(51,"app-icon",52),d(52," Show in graph "),l()(),m(53,je,2,1,"div",53),l()}if(i&2){let e,n=t,a=s(2);o(3),g(n.id),o(),c("text",n.id),o(2),c("state",n.kind),o(),u(n.priority?7:-1),o(2),g(n.title),o(6),g(n.kind),o(),u(n.owner?16:-1),o(5),g(n.sourcePath.replace("specs/","")),o(5),b("",a.selectedSiblings().length," reqs"),o(5),g(a.selectedLinks().length),o(3),c("innerHTML",a.mdHtml(n.body),z),o(3),u(a.detailResource.state().loading?37:a.selectedLinks().length>0?38:39),o(5),c("size",13),o(3),c("size",13),o(3),c("size",13),o(3),c("size",13),o(2),u((e=a.saveError())?53:-1,e)}}function Fe(i,t){i&1&&(r(0,"app-empty",12)(1,"code",61),d(2,"specship init -i"),l()())}function qe(i,t){if(i&1){let e=y();r(0,"div",1)(1,"div",2)(2,"div",3),p(3,"app-icon",4),r(4,"span",5),d(5,"Specs"),l(),p(6,"span",6),r(7,"span",7),d(8),l()(),r(9,"div",8),m(10,ye,1,0,"app-empty",9),I(11,Pe,7,6,null,null,he),l()(),r(13,"div",10),m(14,ze,1,1)(15,We,54,17,"div",11)(16,Fe,3,0,"app-empty",12),l()(),r(17,"app-draft-with-claude-modal",13),x("close",function(){f(e);let a=s();return C(a.onDraftModalClose())}),l()}if(i&2){let e,n=s();o(3),c("size",15),o(5),b(" ",n.resource.state().loading?"\u2026":n.totalCount()+" reqs"," "),o(2),u(n.groups().length===0&&!n.resource.state().loading?10:-1),o(),N(n.groups()),o(3),u(n.editing()?14:(e=n.selectedSpec())?15:16,e),o(3),c("open",n.draftModalOpen())}}function Ge(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\*\*(.+?)\*\*/g,"<strong style='color:var(--text-primary)'>$1</strong>").replace(/`(.+?)`/g,"<code class='mono' style='font-size:12px;background:var(--bg-canvas);padding:1px 5px;border-radius:4px;border:1px solid var(--border-subtle)'>$1</code>")}var ce=class i{api=M(X);projects=M(J);router=M(B);resource=W(this.api,()=>`/api/specs${this.projects.projectQuery()}`);detailResource=W(this.api,()=>{let t=this.sel();return t?`/api/spec/${encodeURIComponent(t)}${this.projects.projectQuery()}`:null});sel=_(null);expandedGroups=_(new Set);editing=_(!1);editingSource=_(null);editingDirty=_(!1);saving=_(!1);saveError=_(null);draftModalOpen=_(!1);STATE=F;groups=h(()=>{let t=this.resource.state().data?.specs??[],e=new Map;for(let n of t){let a=n.sourcePath||"(unknown)";e.has(a)||e.set(a,{path:a,title:a.replace(/^specs\//,""),specs:[]}),e.get(a).specs.push(n)}return[...e.values()]});totalCount=h(()=>this.groups().reduce((t,e)=>t+e.specs.length,0));selectedSpec=h(()=>{let t=this.sel();if(!t)return null;for(let e of this.groups())for(let n of e.specs)if(n.id===t)return n;return null});selectedLinks=h(()=>this.detailResource.state().data?.links??[]);selectedSiblings=h(()=>{let t=this.selectedSpec();if(!t)return[];let e=this.groups().find(n=>n.path===t.sourcePath);return e?e.specs.filter(n=>n.id!==t.id):[]});isGroupOpen(t){return!this.expandedGroups().has("closed:"+t)}toggleGroup(t){this.expandedGroups.update(e=>{let n="closed:"+t,a=new Set(e);return a.has(n)?a.delete(n):a.add(n),a})}driftCountForGroup(t){let e=this.selectedSpec();return!e||e.sourcePath!==t.path?0:this.selectedLinks().filter(n=>["drifted","broken","orphaned"].includes(n.state)).length}stateColorFor(t){return F[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)}mdHtml(t){return Ge(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(),n=await this.api.get(`/api/spec/${encodeURIComponent(t.id)}${e}`);this.editingSource.set(n.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)){this.saving.set(!0),this.saveError.set(null);try{let n=this.projects.projectQuery();await this.api.put(`/api/spec/${encodeURIComponent(t.id)}${n}`,{content:e}),this.editing.set(!1),this.editingDirty.set(!1),this.editingSource.set(null),this.resource.refetch()}catch(n){this.saveError.set(`Save failed: ${n instanceof Error?n.message:String(n)}`)}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||i)};static \u0275cmp=k({type:i,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"],[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"],[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,"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",3,"innerHTML"],[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,"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,n){e&1&&m(0,be,1,0,"app-pick-project-empty",0)(1,qe,18,5),e&2&&u(n.resource.state().noProject?0:1)},dependencies:[Y,E,L,A,ne,Z,ie,ee],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}.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}'],changeDetection:0})};export{ce as Specs};
6
+ `),insertTextRules:P.InsertAsSnippet,documentation:"Insert an implementations block linking the spec to code.",detail:"SpecShip \xB7 implementations",range:a}]}},triggerCharacters:["r","d","a","i"]})}var ve=["host"];function xe(i,t){if(i&1&&(r(0,"span",5),d(1),l()),i&2){let e=s();c("title",e.path),o(),g(e.path)}}function fe(i,t){i&1&&(r(0,"div",15),d(1,"Loading editor\u2026"),l())}var L=class i{sanitizer=y(K);destroyRef=y(G);value="";path="";valueChange=new S;validationChange=new S;save=new S;cancel=new S;hostRef;loading=_(!0);currentValue=_("");errorCount=_(0);warningCount=_(0);dirty=_(!1);previewHtml=C(()=>this.sanitizer.bypassSecurityTrustHtml(ne(this.currentValue()||"")));tokenCount=C(()=>Math.max(1,Math.round((this.currentValue()||"").length/4)));statusLabel=C(()=>{let t=this.errorCount(),e=this.warningCount();return t>0?`${t} error${t===1?"":"s"}`:e>0?`${e} warning${e===1?"":"s"}`:"clean"});statusKind=C(()=>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,le(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;de(this.monaco,this.model);let t=this.monaco.editor.getModelMarkers({resource:this.model.uri,owner:"specship-spec"}),e=t.filter(a=>a.severity===this.monaco.MarkerSeverity.Error).length,n=t.filter(a=>a.severity===this.monaco.MarkerSeverity.Warning).length;this.errorCount.set(e),this.warningCount.set(n),this.validationChange.emit({errors:e,warnings:n})}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||i)};static \u0275cmp=k({type:i,selectors:[["app-spec-editor"]],viewQuery:function(e,n){if(e&1&&H(ve,7),e&2){let a;Q(a=U())&&(n.hostRef=a.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,n){e&1&&(r(0,"div",1)(1,"div",2),p(2,"app-icon",3),r(3,"span",4),d(4,"Spec editor"),l(),m(5,xe,2,2,"span",5),p(6,"span",6),r(7,"span",7),p(8,"span",8),d(9),l(),r(10,"span",9),d(11),l(),r(12,"button",10),x("click",function(){return n.onCancel()}),d(13," Cancel "),l(),r(14,"button",11),x("click",function(){return n.onSave()}),p(15,"app-icon",12),d(16," Save "),l()(),r(17,"div",13)(18,"div",14),m(19,fe,2,0,"div",15),p(20,"div",16,0),l(),p(22,"div",17),l()()),e&2&&(o(2),c("size",14),o(3),u(n.path?5:-1),o(2),R("ok",n.statusKind()==="ok")("warn",n.statusKind()==="warn")("error",n.statusKind()==="error"),o(2),b(" ",n.statusLabel()," "),o(),c("title","~"+n.tokenCount()+" tokens (rough estimate)"),o(),b(" ~",n.tokenCount(),"t "),o(3),c("disabled",!n.dirty()||n.errorCount()>0)("title",n.errorCount()>0?"Fix errors before saving":n.dirty()?"Save changes":"No changes to save"),o(),c("size",13),o(4),u(n.loading()?19:-1),o(3),c("innerHTML",n.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 he(i,t){i&1&&(r(0,"div",14),d(1),l()),i&2&&(o(),g(t))}function Ce(i,t){if(i&1){let e=w();r(0,"div",0),x("click",function(){f(e);let a=s();return h(a.onBackdropClick())}),l(),r(1,"div",1)(2,"header",2)(3,"div",3)(4,"div",4),d(5,"Draft a new spec with Claude"),l(),r(6,"div",5),d(7,"Describe the feature in one sentence. Claude takes it from there."),l()(),r(8,"button",6),x("click",function(){f(e);let a=s();return h(a.onCloseClick())}),p(9,"app-icon",7),l()(),r(10,"div",8)(11,"label",9),d(12,"Feature description"),l(),r(13,"textarea",10),x("input",function(a){f(e);let v=s();return h(v.onDescriptionInput(a))}),l(),r(14,"div",11),d(15,"This will run in Claude Code:"),l(),r(16,"pre",12),d(17),l()(),r(18,"footer",13),m(19,he,2,1,"div",14),p(20,"span",15),r(21,"button",16),x("click",function(){f(e);let a=s();return h(a.onCopyToClipboard())}),p(22,"app-icon",17),d(23," Copy prompt "),l(),r(24,"button",18),x("click",function(){f(e);let a=s();return h(a.onOpenInClaude())}),p(25,"app-icon",19),d(26," Open in Claude Code "),l()()()}if(i&2){let e,n=s();o(9),c("size",16),o(4),c("value",n.description()),o(4),g(n.slashCommand()),o(2),u((e=n.toast())?19:-1,e),o(2),c("disabled",!n.canSubmit()),o(),c("size",13),o(2),c("disabled",!n.canSubmit()),o(),c("size",13)}}var A=class i{open=!1;close=new S;description=_("");toast=_(null);slashCommand=C(()=>{let t=this.description().trim();return t?`/ss-spec-author "${t.replace(/"/g,'\\"')}"`:"/ss-spec-author"});canSubmit=C(()=>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||i)};static \u0275cmp=k({type:i,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,n){e&1&&m(0,Ce,27,8),e&2&&u(n.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 be=(i,t)=>t.path,me=(i,t)=>t.id;function ye(i,t){i&1&&p(0,"app-pick-project-empty",0)}function we(i,t){i&1&&p(0,"app-empty",9)}function Me(i,t){if(i&1&&(r(0,"span",18),d(1),l()),i&2){let e=s().$implicit,n=s(2);o(),b(" ",n.driftCountForGroup(e)," ")}}function Se(i,t){if(i&1){let e=w();r(0,"div",21),x("click",function(){let a=f(e).$implicit,v=s(4);return h(v.select(a.id))}),p(1,"span",22),r(2,"div",23)(3,"div",24),d(4),l(),r(5,"div",25),d(6),l()()()}if(i&2){let e=t.$implicit,n=s(4);R("selected",n.sel()===e.id),o(),$("background",n.stateColorFor(e.kind)),o(2),$("color",n.sel()===e.id?"var(--accent)":"var(--text-primary)"),o(),g(e.id),o(2),g(e.title)}}function Pe(i,t){if(i&1&&(r(0,"div",19),I(1,Se,7,8,"div",20,me),l()),i&2){let e=s().$implicit;o(),N(e.specs)}}function Oe(i,t){if(i&1){let e=w();r(0,"div",14),x("click",function(){let a=f(e).$implicit,v=s(2);return h(v.toggleGroup(a.path))}),p(1,"app-icon",15)(2,"app-icon",16),r(3,"span",17),d(4),l(),m(5,Me,2,1,"span",18),l(),m(6,Pe,3,0,"div",19)}if(i&2){let e=t.$implicit,n=s(2);o(),c("name",n.isGroupOpen(e.path)?"chevronDown":"chevronRight")("size",12),o(),c("size",13),o(2),g(e.title),o(),u(n.driftCountForGroup(e)>0?5:-1),o(),u(n.isGroupOpen(e.path)?6:-1)}}function ke(i,t){if(i&1&&(r(0,"div",26),d(1),l()),i&2){let e=s();o(),b("Loading source for ",e.id,"\u2026")}}function Ee(i,t){if(i&1){let e=w();r(0,"app-spec-editor",30),x("valueChange",function(a){f(e);let v=s(4);return h(v.onEditorValueChange(a))})("save",function(){f(e);let a=s(4);return h(a.onEditorSave())})("cancel",function(){f(e);let a=s(4);return h(a.onEditorCancel())}),l()}if(i&2){let e=s(),n=s(3);c("value",n.editingSource())("path",e.sourcePath)}}function Te(i,t){i&1&&(r(0,"div",28),d(1),l()),i&2&&(o(),g(t))}function De(i,t){i&1&&(r(0,"div",29),d(1,"Saving\u2026"),l())}function ze(i,t){if(i&1&&(m(0,ke,2,1,"div",26)(1,Ee,1,2,"app-spec-editor",27),m(2,Te,2,1,"div",28),m(3,De,2,0,"div",29)),i&2){let e,n=s(3);u(n.editingSource()===null?0:1),o(2),u((e=n.saveError())?2:-1,e),o(),u(n.saving()?3:-1)}}function Ie(i,t){if(i&1&&m(0,ze,4,3),i&2){let e,n=s(2);u((e=n.selectedSpec())?0:-1,e)}}function Ne(i,t){if(i&1&&(r(0,"app-pill"),d(1),l()),i&2){let e=s();o(),g(e.priority)}}function $e(i,t){if(i&1&&(r(0,"div",37)(1,"div",38),d(2,"Owner"),l(),r(3,"div",39),d(4),l()()),i&2){let e=s();o(4),g(e.owner)}}function Re(i,t){i&1&&p(0,"div",42)}function Ve(i,t){if(i&1&&(r(0,"app-pill",56),d(1),l()),i&2){let e=s().$implicit;o(),b("",e.driftAxis," drift")}}function Le(i,t){if(i&1&&(r(0,"div",55),p(1,"app-state-pill",34),m(2,Ve,2,1,"app-pill",56),r(3,"span",57),d(4),l(),r(5,"app-pill"),d(6),l(),r(7,"button",58),p(8,"app-icon",51),d(9," Reveal "),l()()),i&2){let e=t.$implicit,n=t.$index;$("border-top",n>0?"1px solid var(--border-subtle)":"none"),o(),c("state",e.state),o(),u(e.driftAxis?2:-1),o(2),g(e.targetQualifiedName),o(2),g(e.provenance),o(2),c("size",12)}}function Ae(i,t){if(i&1&&(r(0,"div",43),I(1,Le,10,7,"div",54,me),l()),i&2){let e=s(3);o(),N(e.selectedLinks())}}function je(i,t){i&1&&(r(0,"div",44),p(1,"app-icon",59),r(2,"div",60),d(3," Orphaned \u2014 no code implements this requirement yet "),l()()),i&2&&(o(),c("size",16))}function We(i,t){i&1&&(r(0,"div",53),d(1),l()),i&2&&(o(),g(t))}function Fe(i,t){if(i&1){let e=w();r(0,"div",11)(1,"div",31)(2,"span",32),d(3),l(),p(4,"app-copy-btn",33)(5,"div",6)(6,"app-state-pill",34),m(7,Ne,2,1,"app-pill"),l(),r(8,"h1",35),d(9),l(),r(10,"div",36)(11,"div",37)(12,"div",38),d(13,"Kind"),l(),r(14,"div",39),d(15),l()(),m(16,$e,5,1,"div",37),r(17,"div",37)(18,"div",38),d(19,"Doc"),l(),r(20,"div",39),d(21),l()(),r(22,"div",37)(23,"div",38),d(24,"Siblings"),l(),r(25,"div",39),d(26),l()(),r(27,"div",37)(28,"div",38),d(29,"Links"),l(),r(30,"div",39),d(31),l()()(),r(32,"div",40),d(33,"Requirement"),l(),p(34,"div",41),r(35,"div",40),d(36,"Linked code"),l(),m(37,Re,1,0,"div",42)(38,Ae,3,0,"div",43)(39,je,4,1,"div",44),r(40,"div",45)(41,"button",46),p(42,"app-icon",47),d(43," Implement "),l(),r(44,"button",48),p(45,"app-icon",49),d(46," Verify "),l(),r(47,"button",50),x("click",function(){f(e);let a=s(2);return h(a.onEditClick())}),p(48,"app-icon",51),d(49," Edit spec "),l(),r(50,"button",50),x("click",function(){let a=f(e),v=s(2);return h(v.goToGraph(a.id))}),p(51,"app-icon",52),d(52," Show in graph "),l()(),m(53,We,2,1,"div",53),l()}if(i&2){let e,n=t,a=s(2);o(3),g(n.id),o(),c("text",n.id),o(2),c("state",n.kind),o(),u(n.priority?7:-1),o(2),g(n.title),o(6),g(n.kind),o(),u(n.owner?16:-1),o(5),g(n.sourcePath.replace("specs/","")),o(5),b("",a.selectedSiblings().length," reqs"),o(5),g(a.selectedLinks().length),o(3),c("innerHTML",a.mdHtml(n.body),z),o(3),u(a.detailResource.state().loading?37:a.selectedLinks().length>0?38:39),o(5),c("size",13),o(3),c("size",13),o(3),c("size",13),o(3),c("size",13),o(2),u((e=a.saveError())?53:-1,e)}}function qe(i,t){i&1&&(r(0,"app-empty",12)(1,"code",61),d(2,"specship init -i"),l()())}function Ge(i,t){if(i&1){let e=w();r(0,"div",1)(1,"div",2)(2,"div",3),p(3,"app-icon",4),r(4,"span",5),d(5,"Specs"),l(),p(6,"span",6),r(7,"span",7),d(8),l()(),r(9,"div",8),m(10,we,1,0,"app-empty",9),I(11,Oe,7,6,null,null,be),l()(),r(13,"div",10),m(14,Ie,1,1)(15,Fe,54,17,"div",11)(16,qe,3,0,"app-empty",12),l()(),r(17,"app-draft-with-claude-modal",13),x("close",function(){f(e);let a=s();return h(a.onDraftModalClose())}),l()}if(i&2){let e,n=s();o(3),c("size",15),o(5),b(" ",n.resource.state().loading?"\u2026":n.totalCount()+" reqs"," "),o(2),u(n.groups().length===0&&!n.resource.state().loading?10:-1),o(),N(n.groups()),o(3),u(n.editing()?14:(e=n.selectedSpec())?15:16,e),o(3),c("open",n.draftModalOpen())}}function He(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\*\*(.+?)\*\*/g,"<strong style='color:var(--text-primary)'>$1</strong>").replace(/`(.+?)`/g,"<code class='mono' style='font-size:12px;background:var(--bg-canvas);padding:1px 5px;border-radius:4px;border:1px solid var(--border-subtle)'>$1</code>")}var pe=class i{api=y(X);projects=y(J);router=y(B);conn=y(Y);resource=W(this.api,()=>`/api/specs${this.projects.projectQuery()}`);detailResource=W(this.api,()=>{let t=this.sel();return t?`/api/spec/${encodeURIComponent(t)}${this.projects.projectQuery()}`:null});sel=_(null);expandedGroups=_(new Set);editing=_(!1);editingSource=_(null);editingDirty=_(!1);saving=_(!1);saveError=_(null);draftModalOpen=_(!1);STATE=F;groups=C(()=>{let t=this.resource.state().data?.specs??[],e=new Map;for(let n of t){let a=n.sourcePath||"(unknown)";e.has(a)||e.set(a,{path:a,title:a.replace(/^specs\//,""),specs:[]}),e.get(a).specs.push(n)}return[...e.values()]});totalCount=C(()=>this.groups().reduce((t,e)=>t+e.specs.length,0));selectedSpec=C(()=>{let t=this.sel();if(!t)return null;for(let e of this.groups())for(let n of e.specs)if(n.id===t)return n;return null});selectedLinks=C(()=>this.detailResource.state().data?.links??[]);selectedSiblings=C(()=>{let t=this.selectedSpec();if(!t)return[];let e=this.groups().find(n=>n.path===t.sourcePath);return e?e.specs.filter(n=>n.id!==t.id):[]});isGroupOpen(t){return!this.expandedGroups().has("closed:"+t)}toggleGroup(t){this.expandedGroups.update(e=>{let n="closed:"+t,a=new Set(e);return a.has(n)?a.delete(n):a.add(n),a})}driftCountForGroup(t){let e=this.selectedSpec();return!e||e.sourcePath!==t.path?0:this.selectedLinks().filter(n=>["drifted","broken","orphaned"].includes(n.state)).length}stateColorFor(t){return F[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)}mdHtml(t){return He(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(),n=await this.api.get(`/api/spec/${encodeURIComponent(t.id)}${e}`);this.editingSource.set(n.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 n=this.projects.projectQuery();await this.api.put(`/api/spec/${encodeURIComponent(t.id)}${n}`,{content:e}),this.editing.set(!1),this.editingDirty.set(!1),this.editingSource.set(null),this.resource.refetch()}catch(n){this.saveError.set(`Save failed: ${n instanceof Error?n.message:String(n)}`)}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||i)};static \u0275cmp=k({type:i,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"],[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"],[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,"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",3,"innerHTML"],[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,"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,n){e&1&&m(0,ye,1,0,"app-pick-project-empty",0)(1,Ge,18,5),e&2&&u(n.resource.state().noProject?0:1)},dependencies:[Z,E,L,A,ie,ee,oe,te],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}.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}'],changeDetection:0})};export{pe as Specs};
@@ -1,4 +1,4 @@
1
- import{a as j}from"./chunk-G7VZT5KB.js";import{a as G}from"./chunk-R5W2MDZN.js";import{b as V}from"./chunk-4N5DWG46.js";import{a as H}from"./chunk-7RNS77UP.js";import{a as $}from"./chunk-E44X4RH2.js";import{Aa as c,Ga as E,I as z,Ia as P,Ka as m,M as w,N as k,Ta as _,Ua as S,Va as l,W as T,Wa as p,X as A,Xa as y,aa as I,bb as R,ea as o,ka as B,lb as u,qa as M,ra as x,sa as v,ua as N,va as C,wa as h,xa as d,ya as i,yb as U,za as r,zb as K}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var J=()=>[1,2,3,4,5],Y=(n,t)=>t.key,F=(n,t)=>t.id;function X(n,t){n&1&&(i(0,"span",20),c(1,"span",33),l(2," Seed "),r())}function W(n,t){n&1&&(i(0,"span",21),c(1,"span",33),l(2," Live "),r())}function Z(n,t){if(n&1){let e=E();i(0,"div",24),c(1,"app-icon",34),i(2,"div",35)(3,"div",5),l(4,"Couldn't load memory"),r(),i(5,"div",36),l(6),r()(),i(7,"button",37),P("click",function(){w(e);let s=m();return k(s.reload())}),l(8,"Retry"),r()()}n&2&&(o(),d("size",16),o(5),p(t))}function ee(n,t){n&1&&(i(0,"div",25),c(1,"app-icon",38),i(2,"div",35)(3,"div",5),l(4,"No project selected"),r(),i(5,"div",36),l(6,"Pick a project from the top bar to see its CLAUDE.md hierarchy and saved notes."),r()()()),n&2&&(o(),d("size",16))}function te(n,t){n&1&&(i(0,"div",26),c(1,"app-icon",38),i(2,"div",35)(3,"div",5),l(4,"Showing example memory"),r(),i(5,"div",36),l(6,"The selected project has no CLAUDE.md or saved notes yet. The cards below illustrate what real data would look like."),r()()()),n&2&&(o(),d("size",16))}function ne(n,t){if(n&1&&c(0,"span",33),n&2){let e=m().$implicit;_("background",e.color)}}function oe(n,t){if(n&1&&(i(0,"span",41),l(1),r()),n&2){let e=m().$implicit;o(),p(e.count)}}function ie(n,t){if(n&1){let e=E();i(0,"button",39),P("click",function(){let s=w(e).$implicit,g=m();return k(g.onTypeFilter(s.key))}),x(1,ne,1,2,"span",40),l(2),x(3,oe,2,1,"span",41),r()}if(n&2){let e=t.$implicit,a=m();_("--chip-color",e.color)("--chip-bg",e.soft),S("active",a.typeFilter()===e.key),M("aria-pressed",a.typeFilter()===e.key),o(),v(e.key!=="all"?1:-1),o(),y(" ",e.label," "),o(),v(e.count!==void 0?3:-1)}}function re(n,t){if(n&1&&(i(0,"span",30),l(1),r()),n&2){let e=m();o(),p(e.typeDesc())}}function ae(n,t){n&1&&(i(0,"div",48),c(1,"div",49),i(2,"div",50),c(3,"div",51)(4,"div",52),r(),c(5,"div",53),r())}function le(n,t){n&1&&C(0,ae,6,0,"div",48,N),n&2&&h(R(0,J))}function ce(n,t){if(n&1){let e=E();i(0,"button",37),P("click",function(){w(e);let s=m(3);return k(s.clearFilter())}),l(1,"Show all types"),r()}}function de(n,t){if(n&1&&(i(0,"div",44)(1,"div",54),l(2,"Nothing here"),r(),i(3,"div"),l(4),r(),x(5,ce,2,0,"button",55),r()),n&2){let e=m(2);o(4),y("No ",e.filterEmptyNoun()," loaded for this project."),o(),v(e.typeFilter()!=="all"?5:-1)}}function se(n,t){n&1&&c(0,"app-icon",67),n&2&&d("size",10)}function pe(n,t){if(n&1){let e=E();i(0,"button",62),P("click",function(){let s=w(e).$implicit,g=m(4);return k(g.onSelectByObj(s))}),c(1,"span",63)(2,"app-icon",64),i(3,"span",65)(4,"span",66),l(5),x(6,se,1,1,"app-icon",67),r(),i(7,"span",68),l(8),r()(),i(9,"span",69),l(10),r()()}if(n&2){let e=t.$implicit,a=m(4);S("selected",a.selectedId()===e.id)("indent",a.isIndented(e)),M("aria-pressed",a.selectedId()===e.id)("aria-label",a.nameFor(e)+" \u2014 "+a.L[e.level].label),o(),_("background",a.L[e.level].color),o(),d("name",a.iconFor(e))("size",13),o(3),y(" ",a.nameFor(e)," "),o(),v(e.readOnly?6:-1),o(),d("title",a.shortPath(e)),o(),p(a.shortPath(e)),o(2),p(a.fmtK(e.tokens))}}function me(n,t){if(n&1&&(i(0,"div",56)(1,"div",57)(2,"span",58),l(3),r(),i(4,"span",59),l(5),r()(),i(6,"div",60),l(7),r(),C(8,pe,11,15,"button",61,F),r()),n&2){let e=t.$implicit,a=m(3);o(3),p(a.L[e.key].label),o(2),p(a.rowItems(e).length),o(2),p(a.L[e.key].desc),o(),h(a.rowItems(e))}}function ge(n,t){if(n&1&&C(0,me,10,3,"div",56,Y),n&2){let e=m(2);h(e.railGroups())}}function ue(n,t){n&1&&(i(0,"span",72),c(1,"app-icon",86),l(2," read-only"),r()),n&2&&(o(),d("size",10))}function xe(n,t){if(n&1&&(i(0,"div",77)(1,"div",12),l(2,"Saved in"),r(),i(3,"button",87),l(4),r()()),n&2){let e=m();o(3),M("aria-label","Jump to session "+e.session),o(),p(e.session)}}function ve(n,t){if(n&1&&(i(0,"span",88),l(1),r()),n&2){let e=t.$implicit;o(),y("#",e)}}function fe(n,t){if(n&1&&(i(0,"div",79),C(1,ve,2,1,"span",88,N),r()),n&2){let e=m();o(),h(e.tags)}}function _e(n,t){if(n&1&&(i(0,"div",90),c(1,"app-icon",91),i(2,"span",92),l(3),r(),i(4,"span",93),l(5),r()()),n&2){let e=t.$implicit,a=m(4);o(),d("size",12),o(),d("title",e.path),o(),p(e.path),o(2),p(a.fmtK(e.tokens))}}function ye(n,t){if(n&1&&(i(0,"div",81)(1,"div",58),l(2),r(),i(3,"div",89),C(4,_e,6,4,"div",90,F),r()()),n&2){let e=m(3);o(2),y("Imports \xB7 ",e.currentImports().length),o(2),h(e.currentImports())}}function be(n,t){if(n&1&&(i(0,"button",55),c(1,"app-icon",94),l(2),r()),n&2){let e=m();M("aria-label",(e.type==="note"?"Edit note":"Edit memory")+" "+e.path),o(),d("size",13),o(),y(" ",e.type==="note"?"Edit note":"Edit memory"," ")}}function Ce(n,t){if(n&1&&(i(0,"button",85),c(1,"app-icon",95),l(2," Forget "),r()),n&2){let e=m();M("aria-label","Forget note "+e.path),o(),d("size",13)}}function he(n,t){if(n&1&&(i(0,"div",46)(1,"div",70)(2,"span",71),c(3,"app-icon",64),l(4),r(),i(5,"span",71),l(6),r(),i(7,"span",30),l(8),r(),c(9,"span",19),x(10,ue,3,1,"span",72),r(),i(11,"div",73)(12,"span",74),l(13),r(),c(14,"app-copy-btn",75),r(),i(15,"div",76)(16,"div",77)(17,"div",12),l(18,"Tokens"),r(),i(19,"div",78),l(20),r()(),i(21,"div",77)(22,"div",12),l(23,"Lines"),r(),i(24,"div",78),l(25),r()(),i(26,"div",77)(27,"div",12),l(28,"Scope"),r(),i(29,"div",78),l(30),r()(),i(31,"div",77)(32,"div",12),l(33,"Modified"),r(),i(34,"div",78),l(35),r()(),x(36,xe,5,2,"div",77),r(),x(37,fe,3,0,"div",79),c(38,"div",80),x(39,ye,6,1,"div",81),i(40,"div",82),x(41,be,3,3,"button",55),i(42,"button",83),c(43,"app-icon",84),l(44," Copy contents "),r(),x(45,Ce,3,2,"button",85),r()()),n&2){let e=t,a=m(2);o(2),_("background",a.T[e.type].soft)("color",a.T[e.type].color),o(),d("name",a.T[e.type].icon)("size",10),o(),y(" ",a.T[e.type].label," "),o(),_("background",a.L[e.level].soft)("color",a.L[e.level].color),o(),p(a.L[e.level].label),o(2),p(a.L[e.level].desc),o(2),v(e.readOnly?10:-1),o(2),d("title",e.path),o(),p(e.path),o(),d("text",e.path),o(6),p(a.fmtK(e.tokens)),o(5),p(e.lines),o(5),p(a.L[e.level].label),o(5),p(e.modified),o(),v(e.type==="note"&&e.session?36:-1),o(),v(e.type==="note"&&(e.tags!=null&&e.tags.length)?37:-1),o(),d("innerHTML",a.currentBody(),I),o(),v(a.currentImports().length>0?39:-1),o(2),v(e.readOnly?-1:41),o(2),d("size",13),o(2),v(e.type==="note"?45:-1)}}function Me(n,t){n&1&&(i(0,"div",47),c(1,"app-icon",3),i(2,"div"),l(3,"Pick an item from the rail to see its contents."),r()()),n&2&&(o(),d("size",32))}function Pe(n,t){if(n&1&&(i(0,"div",31)(1,"div",42)(2,"div",43),x(3,le,2,1)(4,de,6,2,"div",44)(5,ge,2,0),r()(),i(6,"div",45),x(7,he,46,28,"div",46)(8,Me,4,1,"div",47),r()()),n&2){let e,a=m();o(3),v(a.loading()&&a.source()==="seed"?3:a.visibleCount()===0?4:5),o(4),v((e=a.current())?7:8,e)}}function Oe(n,t){n&1&&c(0,"app-icon",109),n&2&&d("size",11)}function we(n,t){if(n&1&&(i(0,"div",103),c(1,"div",104),i(2,"div",105)(3,"div",106)(4,"span",107),l(5),r(),i(6,"span",71),l(7),r(),i(8,"span",108),l(9),r(),c(10,"span",19),x(11,Oe,1,1,"app-icon",109),i(12,"span",110),l(13),r()(),c(14,"div",111),r()()),n&2){let e=t.$implicit,a=t.$index,s=m(3);o(),_("background",s.L[e.level].color),o(4),p(a+1),o(),_("background",s.L[e.level].soft)("color",s.L[e.level].color),o(),p(s.L[e.level].label),o(),d("title",e.path),o(),p(e.path),o(2),v(e.readOnly?11:-1),o(2),p(s.fmtK(e.tokens)),o(),d("innerHTML",s.renderBody(e.body),I)}}function ke(n,t){if(n&1&&(i(0,"div",101),l(1,"Instructions \xB7 precedence order"),r(),i(2,"div",102),C(3,we,15,13,"div",103,F),r()),n&2){let e=m(2);o(3),h(e.effectiveInstructions())}}function Ee(n,t){n&1&&(i(0,"div",100)(1,"div",54),l(2,"No instructions loaded"),r(),i(3,"div"),l(4,"This project has no CLAUDE.md hierarchy yet."),r()())}function Se(n,t){if(n&1&&(i(0,"div",103),c(1,"div",104),i(2,"div",105)(3,"div",106)(4,"span",71),l(5),r(),i(6,"span",108),l(7),r(),c(8,"span",19),i(9,"span",110),l(10),r()(),c(11,"div",111),r()()),n&2){let e=t.$implicit,a=m(3);o(),_("background",a.L[e.level].color),o(3),_("background",a.L[e.level].soft)("color",a.L[e.level].color),o(),p(a.L[e.level].label),o(),d("title",e.path),o(),p(e.path),o(3),p(a.fmtK(e.tokens)),o(),d("innerHTML",a.renderBody(e.body),I)}}function ze(n,t){if(n&1&&(i(0,"div",112)(1,"span"),l(2,"Notes \xB7 memory tool"),r(),i(3,"span",113),l(4,"retrieved facts, not precedence-ranked"),r()(),i(5,"div",102),C(6,Se,12,11,"div",103,F),r()),n&2){let e=m(2);o(6),h(e.effectiveNotes())}}function Te(n,t){if(n&1&&(i(0,"div",32)(1,"div",96),c(2,"app-icon",97),i(3,"span",98),l(4,"Effective memory"),r(),i(5,"span",30),l(6,"\xB7 everything the agent loads"),r()(),i(7,"div",99),l(8," Instructions merge in precedence order \u2014 managed policy is authoritative, and lower blocks fill in where higher ones are silent. Saved notes are appended as retrieved context. "),r(),x(9,ke,5,0)(10,Ee,5,0,"div",100),x(11,ze,8,0),r()),n&2){let e=m();o(2),d("size",15),o(7),v(e.effectiveInstructions().length>0?9:10),o(2),v(e.effectiveNotes().length>0?11:-1)}}var Q={enterprise:{key:"enterprise",label:"Managed",color:"#E5A50A",soft:"rgba(229,165,10,0.14)",desc:"Organization policy \xB7 cannot be overridden"},user:{key:"user",label:"User",color:"#29D2BE",soft:"rgba(41,210,190,0.14)",desc:"Personal \xB7 applies to every project"},project:{key:"project",label:"Project",color:"#5B93F2",soft:"rgba(91,147,242,0.14)",desc:"Team-shared \xB7 checked into the repo"},subdir:{key:"subdir",label:"Directory",color:"#A586F5",soft:"rgba(165,134,245,0.14)",desc:"Scoped to a subtree \xB7 loaded when cwd is inside"},import:{key:"import",label:"Import",color:"#7B8696",soft:"rgba(123,134,150,0.12)",desc:"Pulled in via @path reference"},note:{key:"note",label:"Notes",color:"#46C26B",soft:"rgba(70,194,107,0.14)",desc:"Agent-written \xB7 memory tool"}},f={instruction:{key:"instruction",label:"Instructions",color:"#5B93F2",soft:"rgba(91,147,242,0.14)",icon:"memory",desc:"Directives & rules from CLAUDE.md"},note:{key:"note",label:"Notes",color:"#46C26B",soft:"rgba(70,194,107,0.14)",icon:"tips",desc:"Facts the agent saved via the memory tool"},import:{key:"import",label:"Imports",color:"#29D2BE",soft:"rgba(41,210,190,0.14)",icon:"external",desc:"Files pulled in via @path"}},Ie=["enterprise","project","subdir","import","user"],Fe=[{id:"m-ent",level:"enterprise",type:"instruction",name:"CLAUDE.md",scope:"managed",readOnly:!0,path:"/Library/Application Support/ClaudeCode/CLAUDE.md",tokens:210,lines:9,modified:"managed",body:"# Engineering policy (managed)\n\n- All code must pass `pnpm lint` and `pnpm typecheck` before commit.\n- Never commit secrets, API keys, or `.env` files.\n- Prefer dependency-free solutions; new deps require review.\n- Validate all external input at trust boundaries.\n- Production logs must not contain user content."},{id:"m-user",level:"user",type:"instruction",name:"CLAUDE.md",scope:"~/.claude",path:"~/.claude/CLAUDE.md",tokens:280,lines:12,modified:"3d ago",body:"# Personal preferences\n\n- Before reading a file, try `specship_explore` for structure first.\n- Use conventional commits (`feat:`, `fix:`, `chore:`).\n- Prefer `rg` over `grep`, `fd` over `find`.\n- Keep responses terse \u2014 show diffs, not whole files.\n- Editor open command: `cursor`.\n- Default model for read/edit turns: Sonnet."},{id:"m-proj",level:"project",type:"instruction",name:"CLAUDE.md",scope:"project root",path:"~/dev/specship/CLAUDE.md",tokens:760,lines:28,modified:"2h ago",imports:["m-imp-conv","m-imp-style"],body:"# SpecShip \u2014 project memory\n\n## Architecture\n- Electron + Angular renderer in `packages/web-ng`.\n- MCP server in `src/mcp`, graph engine in `src/graph`.\n- SQLite via better-sqlite3; migrations in `src/db/migrations.ts`.\n\n## Commands\n- `npm run dev` \u2014 renderer + MCP in watch mode.\n- `npm test` \u2014 vitest; `npm run eval` \u2014 evaluation runner.\n- `npm run cli` \u2014 local SpecShip binary.\n\n## Conventions\n- Spec IDs are stable: `REQ-<AREA>-<NNN>`.\n- Never edit generated files under `src/graph/_gen`.\n\n@docs/conventions.md\n@specs/STYLE.md"},{id:"m-sub",level:"subdir",type:"instruction",name:"CLAUDE.md",scope:"src/graph",path:"~/dev/specship/src/graph/CLAUDE.md",tokens:190,lines:7,modified:"1d ago",body:`# Graph engine notes
1
+ import{a as j}from"./chunk-G7VZT5KB.js";import{a as G}from"./chunk-R5W2MDZN.js";import{c as V}from"./chunk-GR72OOCN.js";import{a as H}from"./chunk-7RNS77UP.js";import{a as $}from"./chunk-E44X4RH2.js";import{Aa as c,Ga as E,I as z,Ia as P,Ka as m,M as w,N as k,Ta as _,Ua as S,Va as l,W as T,Wa as p,X as A,Xa as y,aa as I,bb as R,ea as o,ka as B,lb as u,qa as M,ra as x,sa as v,ua as N,va as C,wa as h,xa as d,ya as i,yb as U,za as r,zb as K}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var J=()=>[1,2,3,4,5],Y=(n,t)=>t.key,F=(n,t)=>t.id;function X(n,t){n&1&&(i(0,"span",20),c(1,"span",33),l(2," Seed "),r())}function W(n,t){n&1&&(i(0,"span",21),c(1,"span",33),l(2," Live "),r())}function Z(n,t){if(n&1){let e=E();i(0,"div",24),c(1,"app-icon",34),i(2,"div",35)(3,"div",5),l(4,"Couldn't load memory"),r(),i(5,"div",36),l(6),r()(),i(7,"button",37),P("click",function(){w(e);let s=m();return k(s.reload())}),l(8,"Retry"),r()()}n&2&&(o(),d("size",16),o(5),p(t))}function ee(n,t){n&1&&(i(0,"div",25),c(1,"app-icon",38),i(2,"div",35)(3,"div",5),l(4,"No project selected"),r(),i(5,"div",36),l(6,"Pick a project from the top bar to see its CLAUDE.md hierarchy and saved notes."),r()()()),n&2&&(o(),d("size",16))}function te(n,t){n&1&&(i(0,"div",26),c(1,"app-icon",38),i(2,"div",35)(3,"div",5),l(4,"Showing example memory"),r(),i(5,"div",36),l(6,"The selected project has no CLAUDE.md or saved notes yet. The cards below illustrate what real data would look like."),r()()()),n&2&&(o(),d("size",16))}function ne(n,t){if(n&1&&c(0,"span",33),n&2){let e=m().$implicit;_("background",e.color)}}function oe(n,t){if(n&1&&(i(0,"span",41),l(1),r()),n&2){let e=m().$implicit;o(),p(e.count)}}function ie(n,t){if(n&1){let e=E();i(0,"button",39),P("click",function(){let s=w(e).$implicit,g=m();return k(g.onTypeFilter(s.key))}),x(1,ne,1,2,"span",40),l(2),x(3,oe,2,1,"span",41),r()}if(n&2){let e=t.$implicit,a=m();_("--chip-color",e.color)("--chip-bg",e.soft),S("active",a.typeFilter()===e.key),M("aria-pressed",a.typeFilter()===e.key),o(),v(e.key!=="all"?1:-1),o(),y(" ",e.label," "),o(),v(e.count!==void 0?3:-1)}}function re(n,t){if(n&1&&(i(0,"span",30),l(1),r()),n&2){let e=m();o(),p(e.typeDesc())}}function ae(n,t){n&1&&(i(0,"div",48),c(1,"div",49),i(2,"div",50),c(3,"div",51)(4,"div",52),r(),c(5,"div",53),r())}function le(n,t){n&1&&C(0,ae,6,0,"div",48,N),n&2&&h(R(0,J))}function ce(n,t){if(n&1){let e=E();i(0,"button",37),P("click",function(){w(e);let s=m(3);return k(s.clearFilter())}),l(1,"Show all types"),r()}}function de(n,t){if(n&1&&(i(0,"div",44)(1,"div",54),l(2,"Nothing here"),r(),i(3,"div"),l(4),r(),x(5,ce,2,0,"button",55),r()),n&2){let e=m(2);o(4),y("No ",e.filterEmptyNoun()," loaded for this project."),o(),v(e.typeFilter()!=="all"?5:-1)}}function se(n,t){n&1&&c(0,"app-icon",67),n&2&&d("size",10)}function pe(n,t){if(n&1){let e=E();i(0,"button",62),P("click",function(){let s=w(e).$implicit,g=m(4);return k(g.onSelectByObj(s))}),c(1,"span",63)(2,"app-icon",64),i(3,"span",65)(4,"span",66),l(5),x(6,se,1,1,"app-icon",67),r(),i(7,"span",68),l(8),r()(),i(9,"span",69),l(10),r()()}if(n&2){let e=t.$implicit,a=m(4);S("selected",a.selectedId()===e.id)("indent",a.isIndented(e)),M("aria-pressed",a.selectedId()===e.id)("aria-label",a.nameFor(e)+" \u2014 "+a.L[e.level].label),o(),_("background",a.L[e.level].color),o(),d("name",a.iconFor(e))("size",13),o(3),y(" ",a.nameFor(e)," "),o(),v(e.readOnly?6:-1),o(),d("title",a.shortPath(e)),o(),p(a.shortPath(e)),o(2),p(a.fmtK(e.tokens))}}function me(n,t){if(n&1&&(i(0,"div",56)(1,"div",57)(2,"span",58),l(3),r(),i(4,"span",59),l(5),r()(),i(6,"div",60),l(7),r(),C(8,pe,11,15,"button",61,F),r()),n&2){let e=t.$implicit,a=m(3);o(3),p(a.L[e.key].label),o(2),p(a.rowItems(e).length),o(2),p(a.L[e.key].desc),o(),h(a.rowItems(e))}}function ge(n,t){if(n&1&&C(0,me,10,3,"div",56,Y),n&2){let e=m(2);h(e.railGroups())}}function ue(n,t){n&1&&(i(0,"span",72),c(1,"app-icon",86),l(2," read-only"),r()),n&2&&(o(),d("size",10))}function xe(n,t){if(n&1&&(i(0,"div",77)(1,"div",12),l(2,"Saved in"),r(),i(3,"button",87),l(4),r()()),n&2){let e=m();o(3),M("aria-label","Jump to session "+e.session),o(),p(e.session)}}function ve(n,t){if(n&1&&(i(0,"span",88),l(1),r()),n&2){let e=t.$implicit;o(),y("#",e)}}function fe(n,t){if(n&1&&(i(0,"div",79),C(1,ve,2,1,"span",88,N),r()),n&2){let e=m();o(),h(e.tags)}}function _e(n,t){if(n&1&&(i(0,"div",90),c(1,"app-icon",91),i(2,"span",92),l(3),r(),i(4,"span",93),l(5),r()()),n&2){let e=t.$implicit,a=m(4);o(),d("size",12),o(),d("title",e.path),o(),p(e.path),o(2),p(a.fmtK(e.tokens))}}function ye(n,t){if(n&1&&(i(0,"div",81)(1,"div",58),l(2),r(),i(3,"div",89),C(4,_e,6,4,"div",90,F),r()()),n&2){let e=m(3);o(2),y("Imports \xB7 ",e.currentImports().length),o(2),h(e.currentImports())}}function be(n,t){if(n&1&&(i(0,"button",55),c(1,"app-icon",94),l(2),r()),n&2){let e=m();M("aria-label",(e.type==="note"?"Edit note":"Edit memory")+" "+e.path),o(),d("size",13),o(),y(" ",e.type==="note"?"Edit note":"Edit memory"," ")}}function Ce(n,t){if(n&1&&(i(0,"button",85),c(1,"app-icon",95),l(2," Forget "),r()),n&2){let e=m();M("aria-label","Forget note "+e.path),o(),d("size",13)}}function he(n,t){if(n&1&&(i(0,"div",46)(1,"div",70)(2,"span",71),c(3,"app-icon",64),l(4),r(),i(5,"span",71),l(6),r(),i(7,"span",30),l(8),r(),c(9,"span",19),x(10,ue,3,1,"span",72),r(),i(11,"div",73)(12,"span",74),l(13),r(),c(14,"app-copy-btn",75),r(),i(15,"div",76)(16,"div",77)(17,"div",12),l(18,"Tokens"),r(),i(19,"div",78),l(20),r()(),i(21,"div",77)(22,"div",12),l(23,"Lines"),r(),i(24,"div",78),l(25),r()(),i(26,"div",77)(27,"div",12),l(28,"Scope"),r(),i(29,"div",78),l(30),r()(),i(31,"div",77)(32,"div",12),l(33,"Modified"),r(),i(34,"div",78),l(35),r()(),x(36,xe,5,2,"div",77),r(),x(37,fe,3,0,"div",79),c(38,"div",80),x(39,ye,6,1,"div",81),i(40,"div",82),x(41,be,3,3,"button",55),i(42,"button",83),c(43,"app-icon",84),l(44," Copy contents "),r(),x(45,Ce,3,2,"button",85),r()()),n&2){let e=t,a=m(2);o(2),_("background",a.T[e.type].soft)("color",a.T[e.type].color),o(),d("name",a.T[e.type].icon)("size",10),o(),y(" ",a.T[e.type].label," "),o(),_("background",a.L[e.level].soft)("color",a.L[e.level].color),o(),p(a.L[e.level].label),o(2),p(a.L[e.level].desc),o(2),v(e.readOnly?10:-1),o(2),d("title",e.path),o(),p(e.path),o(),d("text",e.path),o(6),p(a.fmtK(e.tokens)),o(5),p(e.lines),o(5),p(a.L[e.level].label),o(5),p(e.modified),o(),v(e.type==="note"&&e.session?36:-1),o(),v(e.type==="note"&&(e.tags!=null&&e.tags.length)?37:-1),o(),d("innerHTML",a.currentBody(),I),o(),v(a.currentImports().length>0?39:-1),o(2),v(e.readOnly?-1:41),o(2),d("size",13),o(2),v(e.type==="note"?45:-1)}}function Me(n,t){n&1&&(i(0,"div",47),c(1,"app-icon",3),i(2,"div"),l(3,"Pick an item from the rail to see its contents."),r()()),n&2&&(o(),d("size",32))}function Pe(n,t){if(n&1&&(i(0,"div",31)(1,"div",42)(2,"div",43),x(3,le,2,1)(4,de,6,2,"div",44)(5,ge,2,0),r()(),i(6,"div",45),x(7,he,46,28,"div",46)(8,Me,4,1,"div",47),r()()),n&2){let e,a=m();o(3),v(a.loading()&&a.source()==="seed"?3:a.visibleCount()===0?4:5),o(4),v((e=a.current())?7:8,e)}}function Oe(n,t){n&1&&c(0,"app-icon",109),n&2&&d("size",11)}function we(n,t){if(n&1&&(i(0,"div",103),c(1,"div",104),i(2,"div",105)(3,"div",106)(4,"span",107),l(5),r(),i(6,"span",71),l(7),r(),i(8,"span",108),l(9),r(),c(10,"span",19),x(11,Oe,1,1,"app-icon",109),i(12,"span",110),l(13),r()(),c(14,"div",111),r()()),n&2){let e=t.$implicit,a=t.$index,s=m(3);o(),_("background",s.L[e.level].color),o(4),p(a+1),o(),_("background",s.L[e.level].soft)("color",s.L[e.level].color),o(),p(s.L[e.level].label),o(),d("title",e.path),o(),p(e.path),o(2),v(e.readOnly?11:-1),o(2),p(s.fmtK(e.tokens)),o(),d("innerHTML",s.renderBody(e.body),I)}}function ke(n,t){if(n&1&&(i(0,"div",101),l(1,"Instructions \xB7 precedence order"),r(),i(2,"div",102),C(3,we,15,13,"div",103,F),r()),n&2){let e=m(2);o(3),h(e.effectiveInstructions())}}function Ee(n,t){n&1&&(i(0,"div",100)(1,"div",54),l(2,"No instructions loaded"),r(),i(3,"div"),l(4,"This project has no CLAUDE.md hierarchy yet."),r()())}function Se(n,t){if(n&1&&(i(0,"div",103),c(1,"div",104),i(2,"div",105)(3,"div",106)(4,"span",71),l(5),r(),i(6,"span",108),l(7),r(),c(8,"span",19),i(9,"span",110),l(10),r()(),c(11,"div",111),r()()),n&2){let e=t.$implicit,a=m(3);o(),_("background",a.L[e.level].color),o(3),_("background",a.L[e.level].soft)("color",a.L[e.level].color),o(),p(a.L[e.level].label),o(),d("title",e.path),o(),p(e.path),o(3),p(a.fmtK(e.tokens)),o(),d("innerHTML",a.renderBody(e.body),I)}}function ze(n,t){if(n&1&&(i(0,"div",112)(1,"span"),l(2,"Notes \xB7 memory tool"),r(),i(3,"span",113),l(4,"retrieved facts, not precedence-ranked"),r()(),i(5,"div",102),C(6,Se,12,11,"div",103,F),r()),n&2){let e=m(2);o(6),h(e.effectiveNotes())}}function Te(n,t){if(n&1&&(i(0,"div",32)(1,"div",96),c(2,"app-icon",97),i(3,"span",98),l(4,"Effective memory"),r(),i(5,"span",30),l(6,"\xB7 everything the agent loads"),r()(),i(7,"div",99),l(8," Instructions merge in precedence order \u2014 managed policy is authoritative, and lower blocks fill in where higher ones are silent. Saved notes are appended as retrieved context. "),r(),x(9,ke,5,0)(10,Ee,5,0,"div",100),x(11,ze,8,0),r()),n&2){let e=m();o(2),d("size",15),o(7),v(e.effectiveInstructions().length>0?9:10),o(2),v(e.effectiveNotes().length>0?11:-1)}}var Q={enterprise:{key:"enterprise",label:"Managed",color:"#E5A50A",soft:"rgba(229,165,10,0.14)",desc:"Organization policy \xB7 cannot be overridden"},user:{key:"user",label:"User",color:"#29D2BE",soft:"rgba(41,210,190,0.14)",desc:"Personal \xB7 applies to every project"},project:{key:"project",label:"Project",color:"#5B93F2",soft:"rgba(91,147,242,0.14)",desc:"Team-shared \xB7 checked into the repo"},subdir:{key:"subdir",label:"Directory",color:"#A586F5",soft:"rgba(165,134,245,0.14)",desc:"Scoped to a subtree \xB7 loaded when cwd is inside"},import:{key:"import",label:"Import",color:"#7B8696",soft:"rgba(123,134,150,0.12)",desc:"Pulled in via @path reference"},note:{key:"note",label:"Notes",color:"#46C26B",soft:"rgba(70,194,107,0.14)",desc:"Agent-written \xB7 memory tool"}},f={instruction:{key:"instruction",label:"Instructions",color:"#5B93F2",soft:"rgba(91,147,242,0.14)",icon:"memory",desc:"Directives & rules from CLAUDE.md"},note:{key:"note",label:"Notes",color:"#46C26B",soft:"rgba(70,194,107,0.14)",icon:"tips",desc:"Facts the agent saved via the memory tool"},import:{key:"import",label:"Imports",color:"#29D2BE",soft:"rgba(41,210,190,0.14)",icon:"external",desc:"Files pulled in via @path"}},Ie=["enterprise","project","subdir","import","user"],Fe=[{id:"m-ent",level:"enterprise",type:"instruction",name:"CLAUDE.md",scope:"managed",readOnly:!0,path:"/Library/Application Support/ClaudeCode/CLAUDE.md",tokens:210,lines:9,modified:"managed",body:"# Engineering policy (managed)\n\n- All code must pass `pnpm lint` and `pnpm typecheck` before commit.\n- Never commit secrets, API keys, or `.env` files.\n- Prefer dependency-free solutions; new deps require review.\n- Validate all external input at trust boundaries.\n- Production logs must not contain user content."},{id:"m-user",level:"user",type:"instruction",name:"CLAUDE.md",scope:"~/.claude",path:"~/.claude/CLAUDE.md",tokens:280,lines:12,modified:"3d ago",body:"# Personal preferences\n\n- Before reading a file, try `specship_explore` for structure first.\n- Use conventional commits (`feat:`, `fix:`, `chore:`).\n- Prefer `rg` over `grep`, `fd` over `find`.\n- Keep responses terse \u2014 show diffs, not whole files.\n- Editor open command: `cursor`.\n- Default model for read/edit turns: Sonnet."},{id:"m-proj",level:"project",type:"instruction",name:"CLAUDE.md",scope:"project root",path:"~/dev/specship/CLAUDE.md",tokens:760,lines:28,modified:"2h ago",imports:["m-imp-conv","m-imp-style"],body:"# SpecShip \u2014 project memory\n\n## Architecture\n- Electron + Angular renderer in `packages/web-ng`.\n- MCP server in `src/mcp`, graph engine in `src/graph`.\n- SQLite via better-sqlite3; migrations in `src/db/migrations.ts`.\n\n## Commands\n- `npm run dev` \u2014 renderer + MCP in watch mode.\n- `npm test` \u2014 vitest; `npm run eval` \u2014 evaluation runner.\n- `npm run cli` \u2014 local SpecShip binary.\n\n## Conventions\n- Spec IDs are stable: `REQ-<AREA>-<NNN>`.\n- Never edit generated files under `src/graph/_gen`.\n\n@docs/conventions.md\n@specs/STYLE.md"},{id:"m-sub",level:"subdir",type:"instruction",name:"CLAUDE.md",scope:"src/graph",path:"~/dev/specship/src/graph/CLAUDE.md",tokens:190,lines:7,modified:"1d ago",body:`# Graph engine notes
2
2
 
3
3
  - Layout runs in a worker \u2014 keep \`applyLayout\` pure.
4
4
  - Node positions are cached by content hash.
@@ -1 +1 @@
1
- import{a as R}from"./chunk-X2HTISHL.js";import{a as V}from"./chunk-UYC52MBC.js";import{a as $}from"./chunk-R5W2MDZN.js";import{b as N}from"./chunk-4N5DWG46.js";import"./chunk-7RNS77UP.js";import{a as F}from"./chunk-E44X4RH2.js";import{Aa as p,Ea as S,Fa as T,Ga as h,I as P,Ia as O,Ka as c,M as b,N as y,Ta as E,Ua as I,Va as s,W as C,Wa as l,Xa as g,bb as D,ea as o,ka as z,lb as M,qa as k,ra as x,sa as _,ua as w,va as u,wa as f,xa as d,ya as a,za as r,zb as B}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var j=()=>[0,1,2,3],H=(n,t)=>t.id;function q(n,t){n&1&&p(0,"div",6)}function G(n,t){n&1&&u(0,q,1,0,"div",6,w),n&2&&f(D(0,j))}function J(n,t){n&1&&(a(0,"div",4),s(1,"No tips."),r())}function K(n,t){if(n&1&&p(0,"app-icon",13),n&2){let e=c().$implicit;d("name",e.icon)("size",15)}}function L(n,t){n&1&&p(0,"app-icon",14),n&2&&d("size",15)}function Q(n,t){if(n&1){let e=h();a(0,"div",37),O("click",function(){b(e);let m=c(2).$implicit,v=c(2);return y(v.dismiss(m.id))}),s(1),r()}if(n&2){let e=t.$implicit;o(),g("Snooze ",e)}}function U(n,t){if(n&1&&(a(0,"div",35),u(1,Q,2,1,"div",36,w),r()),n&2){let e=c(3);o(),f(e.snoozeOpts)}}function W(n,t){if(n&1){let e=h();a(0,"div",8),p(1,"div",9),a(2,"div",10)(3,"div",11)(4,"div",12),x(5,K,1,2,"app-icon",13)(6,L,1,1,"app-icon",14),r(),a(7,"div",15)(8,"div",16),s(9),r()(),a(10,"app-pill",3),s(11),r()(),a(12,"div",17),s(13),r(),a(14,"div",18)(15,"div",19)(16,"div",20),s(17,"Evidence"),r(),a(18,"div",21),p(19,"app-icon",22),a(20,"span",23),s(21),r()(),a(22,"div",24),s(23),r()(),a(24,"div",19)(25,"div",20),s(26,"Impact"),r(),a(27,"div",25),s(28),r()()(),a(29,"div",26)(30,"div",27)(31,"span",28),s(32,"fix"),r(),a(33,"code",29),s(34),r(),p(35,"app-copy-btn",30),r(),a(36,"button",31),s(37,"Apply"),r(),a(38,"div",32)(39,"button",33),O("click",function(){let m=b(e).$implicit,v=c(2);return y(v.toggleSnooze(m.id))}),s(40," Dismiss "),p(41,"app-icon",34),r(),x(42,U,3,0,"div",35),r()()()()}if(n&2){let e=t.$implicit,i=c(2);I("dismissed",i.isDismissed(e.id)),k("data-sev",e.severity),o(4),E("background",i.sevBg(e.severity))("color",i.sevColor(e.severity)),o(),_(e.icon?5:6),o(4),l(e.title),o(),d("color",i.sevColor(e.severity))("bg",i.sevBg(e.severity)),o(),l(e.severity),o(2),l(e.why),o(6),d("size",11),o(2),l(e.evidence.session),o(2),l(e.evidence.detail),o(5),l(e.saving),o(6),l(e.fix),o(),d("text",e.fix),o(6),d("size",12),o(),_(i.snoozeOpen(e.id)?42:-1)}}function X(n,t){if(n&1&&(a(0,"div",5),u(1,W,43,21,"div",7,H),r()),n&2){let e=c();o(),f(e.ordered())}}var A=class n{api=P(F);resource=N(this.api,()=>"/api/claude/tips");dismissedIds=C(new Set);snoozeOpenIds=C(new Set);snoozeOpts=["1 day","1 week","Forever"];ordered=M(()=>{let t=this.resource.state().data?.tips??[],e=this.dismissedIds(),i={error:0,warn:1,info:2};return[...t].filter(m=>!e.has(m.id)).sort((m,v)=>(i[m.severity]??9)-(i[v.severity]??9))});counts=M(()=>{let t=this.resource.state().data?.tips??[];return{error:t.filter(e=>e.severity==="error").length,warn:t.filter(e=>e.severity==="warn").length,info:t.filter(e=>e.severity==="info").length}});isDismissed(t){return this.dismissedIds().has(t)}snoozeOpen(t){return this.snoozeOpenIds().has(t)}toggleSnooze(t){this.snoozeOpenIds.update(e=>{let i=new Set(e);return i.has(t)?i.delete(t):i.add(t),i})}dismiss(t){this.dismissedIds.update(e=>new Set([...e,t])),this.snoozeOpenIds.update(e=>{let i=new Set(e);return i.delete(t),i})}sevColor(t){return t==="error"?"var(--error)":t==="warn"?"var(--warn)":"var(--info)"}sevBg(t){return t==="error"?"color-mix(in srgb, var(--error) 16%, transparent)":t==="warn"?"color-mix(in srgb, var(--warn) 16%, transparent)":"color-mix(in srgb, var(--info) 16%, transparent)"}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=z({type:n,selectors:[["app-tips"]],decls:12,vars:10,consts:[[1,"page","scroll-y"],["icon","tips","title","Tips","sub","A senior teammate reviewed your transcripts"],["actions",""],[3,"color","bg"],[1,"empty"],[1,"tips-grid"],[1,"skel","card-skel"],[1,"tip-card","card",3,"dismissed"],[1,"tip-card","card"],[1,"sev-bar"],[1,"tip-body"],[1,"row","gap-10",2,"margin-bottom","10px"],[1,"icon-tile"],[3,"name","size"],["name","tips",3,"size"],[1,"grow",2,"min-width","0"],[1,"tip-title"],[1,"tip-why"],[1,"tip-grid"],[1,"kv-block"],[1,"eyebrow"],[1,"row","gap-6",2,"font-size","11.5px","margin-top","2px"],["name","sessions",2,"color","var(--text-muted)",3,"size"],[1,"mono",2,"color","var(--accent)"],[1,"mono","secondary",2,"font-size","11px","margin-top","4px"],[2,"font-size","16px","font-weight","700","color","var(--success)","font-variant-numeric","tabular-nums","margin-top","2px"],[1,"actions"],[1,"fix-row","grow"],[1,"muted","fix-label"],[1,"mono","fix-code"],[3,"text"],["type","button",1,"btn","btn-primary","btn-sm"],[1,"dismiss-wrap",2,"position","relative"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","chevronDown",3,"size"],[1,"snooze-menu"],[1,"snooze-opt"],[1,"snooze-opt",3,"click"]],template:function(e,i){e&1&&(a(0,"div",0)(1,"app-page-head",1),S(2,2),a(3,"app-pill",3),s(4),r(),a(5,"app-pill",3),s(6),r(),a(7,"app-pill",3),s(8),r(),T(),r(),x(9,G,2,1)(10,J,2,0,"div",4)(11,X,3,0,"div",5),r()),e&2&&(o(3),d("color","var(--error)")("bg","var(--error-soft)"),o(),g("",i.counts().error," urgent"),o(),d("color","var(--warn)")("bg","var(--warn-soft)"),o(),g("",i.counts().warn," warn"),o(),d("color","var(--info)")("bg","var(--info-soft)"),o(),g("",i.counts().info," info"),o(),_(i.resource.state().loading?9:i.ordered().length===0?10:11))},dependencies:[V,R,$,B],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.secondary[_ngcontent-%COMP%]{color:var(--text-secondary)}.grow[_ngcontent-%COMP%]{flex:1}.tips-grid[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;max-width:860px}.tip-card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);overflow:hidden;display:flex}.tip-card.dismissed[_ngcontent-%COMP%]{display:none}.tip-card[data-sev=error][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--error)}.tip-card[data-sev=warn][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--warn)}.tip-card[data-sev=info][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--info)}.sev-bar[_ngcontent-%COMP%]{width:3px;flex-shrink:0}.tip-body[_ngcontent-%COMP%]{padding:14px 16px;flex:1;min-width:0}.icon-tile[_ngcontent-%COMP%]{width:28px;height:28px;border-radius:8px;display:grid;place-items:center;flex-shrink:0}.tip-title[_ngcontent-%COMP%]{font-size:14px;font-weight:600;letter-spacing:-.01em;text-wrap:pretty}.tip-why[_ngcontent-%COMP%]{color:var(--text-secondary);font-size:12.5px;line-height:1.6;margin-bottom:12px}.tip-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}.kv-block[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:var(--r-md);padding:10px}.eyebrow[_ngcontent-%COMP%]{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted);margin-bottom:5px}.actions[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.fix-row[_ngcontent-%COMP%]{min-width:0;display:flex;align-items:center;gap:8px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:6px 10px}.fix-label[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;flex-shrink:0}.fix-code[_ngcontent-%COMP%]{flex:1;min-width:0;color:var(--text-primary);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dismiss-wrap[_ngcontent-%COMP%]{position:relative}.snooze-menu[_ngcontent-%COMP%]{position:absolute;top:100%;right:0;margin-top:4px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:8px;box-shadow:0 4px 16px #00000059;padding:5px;width:130px;z-index:10}.snooze-opt[_ngcontent-%COMP%]{padding:6px 9px;border-radius:5px;cursor:pointer;font-size:12px;color:var(--text-primary)}.snooze-opt[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.card-skel[_ngcontent-%COMP%]{height:200px;margin-bottom:12px}.empty[_ngcontent-%COMP%]{color:var(--text-muted);font-size:13px;padding:40px;text-align:center}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{A as Tips};
1
+ import{a as R}from"./chunk-X2HTISHL.js";import{a as V}from"./chunk-UYC52MBC.js";import{a as $}from"./chunk-R5W2MDZN.js";import{c as N}from"./chunk-GR72OOCN.js";import"./chunk-7RNS77UP.js";import{a as F}from"./chunk-E44X4RH2.js";import{Aa as p,Ea as S,Fa as T,Ga as h,I as P,Ia as O,Ka as c,M as b,N as y,Ta as E,Ua as I,Va as s,W as C,Wa as l,Xa as g,bb as D,ea as o,ka as z,lb as M,qa as k,ra as x,sa as _,ua as w,va as u,wa as f,xa as d,ya as a,za as r,zb as B}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var j=()=>[0,1,2,3],H=(n,t)=>t.id;function q(n,t){n&1&&p(0,"div",6)}function G(n,t){n&1&&u(0,q,1,0,"div",6,w),n&2&&f(D(0,j))}function J(n,t){n&1&&(a(0,"div",4),s(1,"No tips."),r())}function K(n,t){if(n&1&&p(0,"app-icon",13),n&2){let e=c().$implicit;d("name",e.icon)("size",15)}}function L(n,t){n&1&&p(0,"app-icon",14),n&2&&d("size",15)}function Q(n,t){if(n&1){let e=h();a(0,"div",37),O("click",function(){b(e);let m=c(2).$implicit,v=c(2);return y(v.dismiss(m.id))}),s(1),r()}if(n&2){let e=t.$implicit;o(),g("Snooze ",e)}}function U(n,t){if(n&1&&(a(0,"div",35),u(1,Q,2,1,"div",36,w),r()),n&2){let e=c(3);o(),f(e.snoozeOpts)}}function W(n,t){if(n&1){let e=h();a(0,"div",8),p(1,"div",9),a(2,"div",10)(3,"div",11)(4,"div",12),x(5,K,1,2,"app-icon",13)(6,L,1,1,"app-icon",14),r(),a(7,"div",15)(8,"div",16),s(9),r()(),a(10,"app-pill",3),s(11),r()(),a(12,"div",17),s(13),r(),a(14,"div",18)(15,"div",19)(16,"div",20),s(17,"Evidence"),r(),a(18,"div",21),p(19,"app-icon",22),a(20,"span",23),s(21),r()(),a(22,"div",24),s(23),r()(),a(24,"div",19)(25,"div",20),s(26,"Impact"),r(),a(27,"div",25),s(28),r()()(),a(29,"div",26)(30,"div",27)(31,"span",28),s(32,"fix"),r(),a(33,"code",29),s(34),r(),p(35,"app-copy-btn",30),r(),a(36,"button",31),s(37,"Apply"),r(),a(38,"div",32)(39,"button",33),O("click",function(){let m=b(e).$implicit,v=c(2);return y(v.toggleSnooze(m.id))}),s(40," Dismiss "),p(41,"app-icon",34),r(),x(42,U,3,0,"div",35),r()()()()}if(n&2){let e=t.$implicit,i=c(2);I("dismissed",i.isDismissed(e.id)),k("data-sev",e.severity),o(4),E("background",i.sevBg(e.severity))("color",i.sevColor(e.severity)),o(),_(e.icon?5:6),o(4),l(e.title),o(),d("color",i.sevColor(e.severity))("bg",i.sevBg(e.severity)),o(),l(e.severity),o(2),l(e.why),o(6),d("size",11),o(2),l(e.evidence.session),o(2),l(e.evidence.detail),o(5),l(e.saving),o(6),l(e.fix),o(),d("text",e.fix),o(6),d("size",12),o(),_(i.snoozeOpen(e.id)?42:-1)}}function X(n,t){if(n&1&&(a(0,"div",5),u(1,W,43,21,"div",7,H),r()),n&2){let e=c();o(),f(e.ordered())}}var A=class n{api=P(F);resource=N(this.api,()=>"/api/claude/tips");dismissedIds=C(new Set);snoozeOpenIds=C(new Set);snoozeOpts=["1 day","1 week","Forever"];ordered=M(()=>{let t=this.resource.state().data?.tips??[],e=this.dismissedIds(),i={error:0,warn:1,info:2};return[...t].filter(m=>!e.has(m.id)).sort((m,v)=>(i[m.severity]??9)-(i[v.severity]??9))});counts=M(()=>{let t=this.resource.state().data?.tips??[];return{error:t.filter(e=>e.severity==="error").length,warn:t.filter(e=>e.severity==="warn").length,info:t.filter(e=>e.severity==="info").length}});isDismissed(t){return this.dismissedIds().has(t)}snoozeOpen(t){return this.snoozeOpenIds().has(t)}toggleSnooze(t){this.snoozeOpenIds.update(e=>{let i=new Set(e);return i.has(t)?i.delete(t):i.add(t),i})}dismiss(t){this.dismissedIds.update(e=>new Set([...e,t])),this.snoozeOpenIds.update(e=>{let i=new Set(e);return i.delete(t),i})}sevColor(t){return t==="error"?"var(--error)":t==="warn"?"var(--warn)":"var(--info)"}sevBg(t){return t==="error"?"color-mix(in srgb, var(--error) 16%, transparent)":t==="warn"?"color-mix(in srgb, var(--warn) 16%, transparent)":"color-mix(in srgb, var(--info) 16%, transparent)"}static \u0275fac=function(e){return new(e||n)};static \u0275cmp=z({type:n,selectors:[["app-tips"]],decls:12,vars:10,consts:[[1,"page","scroll-y"],["icon","tips","title","Tips","sub","A senior teammate reviewed your transcripts"],["actions",""],[3,"color","bg"],[1,"empty"],[1,"tips-grid"],[1,"skel","card-skel"],[1,"tip-card","card",3,"dismissed"],[1,"tip-card","card"],[1,"sev-bar"],[1,"tip-body"],[1,"row","gap-10",2,"margin-bottom","10px"],[1,"icon-tile"],[3,"name","size"],["name","tips",3,"size"],[1,"grow",2,"min-width","0"],[1,"tip-title"],[1,"tip-why"],[1,"tip-grid"],[1,"kv-block"],[1,"eyebrow"],[1,"row","gap-6",2,"font-size","11.5px","margin-top","2px"],["name","sessions",2,"color","var(--text-muted)",3,"size"],[1,"mono",2,"color","var(--accent)"],[1,"mono","secondary",2,"font-size","11px","margin-top","4px"],[2,"font-size","16px","font-weight","700","color","var(--success)","font-variant-numeric","tabular-nums","margin-top","2px"],[1,"actions"],[1,"fix-row","grow"],[1,"muted","fix-label"],[1,"mono","fix-code"],[3,"text"],["type","button",1,"btn","btn-primary","btn-sm"],[1,"dismiss-wrap",2,"position","relative"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","chevronDown",3,"size"],[1,"snooze-menu"],[1,"snooze-opt"],[1,"snooze-opt",3,"click"]],template:function(e,i){e&1&&(a(0,"div",0)(1,"app-page-head",1),S(2,2),a(3,"app-pill",3),s(4),r(),a(5,"app-pill",3),s(6),r(),a(7,"app-pill",3),s(8),r(),T(),r(),x(9,G,2,1)(10,J,2,0,"div",4)(11,X,3,0,"div",5),r()),e&2&&(o(3),d("color","var(--error)")("bg","var(--error-soft)"),o(),g("",i.counts().error," urgent"),o(),d("color","var(--warn)")("bg","var(--warn-soft)"),o(),g("",i.counts().warn," warn"),o(),d("color","var(--info)")("bg","var(--info-soft)"),o(),g("",i.counts().info," info"),o(),_(i.resource.state().loading?9:i.ordered().length===0?10:11))},dependencies:[V,R,$,B],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.secondary[_ngcontent-%COMP%]{color:var(--text-secondary)}.grow[_ngcontent-%COMP%]{flex:1}.tips-grid[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px;max-width:860px}.tip-card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);overflow:hidden;display:flex}.tip-card.dismissed[_ngcontent-%COMP%]{display:none}.tip-card[data-sev=error][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--error)}.tip-card[data-sev=warn][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--warn)}.tip-card[data-sev=info][_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{background:var(--info)}.sev-bar[_ngcontent-%COMP%]{width:3px;flex-shrink:0}.tip-body[_ngcontent-%COMP%]{padding:14px 16px;flex:1;min-width:0}.icon-tile[_ngcontent-%COMP%]{width:28px;height:28px;border-radius:8px;display:grid;place-items:center;flex-shrink:0}.tip-title[_ngcontent-%COMP%]{font-size:14px;font-weight:600;letter-spacing:-.01em;text-wrap:pretty}.tip-why[_ngcontent-%COMP%]{color:var(--text-secondary);font-size:12.5px;line-height:1.6;margin-bottom:12px}.tip-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}.kv-block[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:var(--r-md);padding:10px}.eyebrow[_ngcontent-%COMP%]{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted);margin-bottom:5px}.actions[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.fix-row[_ngcontent-%COMP%]{min-width:0;display:flex;align-items:center;gap:8px;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:6px 10px}.fix-label[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;flex-shrink:0}.fix-code[_ngcontent-%COMP%]{flex:1;min-width:0;color:var(--text-primary);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dismiss-wrap[_ngcontent-%COMP%]{position:relative}.snooze-menu[_ngcontent-%COMP%]{position:absolute;top:100%;right:0;margin-top:4px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:8px;box-shadow:0 4px 16px #00000059;padding:5px;width:130px;z-index:10}.snooze-opt[_ngcontent-%COMP%]{padding:6px 9px;border-radius:5px;cursor:pointer;font-size:12px;color:var(--text-primary)}.snooze-opt[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.card-skel[_ngcontent-%COMP%]{height:200px;margin-bottom:12px}.empty[_ngcontent-%COMP%]{color:var(--text-muted);font-size:13px;padding:40px;text-align:center}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{A as Tips};
@@ -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{a as Y,b as G}from"./chunk-4N5DWG46.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{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 +1 @@
1
- import{a as oe}from"./chunk-MC4DFIHG.js";import{a as te}from"./chunk-UYC52MBC.js";import{a as ne}from"./chunk-SUZYBYDW.js";import{b as Q}from"./chunk-4N5DWG46.js";import"./chunk-7RNS77UP.js";import{a as J}from"./chunk-E44X4RH2.js";import{Aa as _,Ba as C,Ca as M,Da as $,Ea as j,Fa as G,I as B,Ia as I,Ja as V,Ka as u,O as w,P as A,Ta as k,Ua as K,Va as c,W as F,Wa as d,Xa as z,Ya as Y,bb as E,ea as a,fb as Z,gb as U,ib as W,ka as P,lb as p,ob as X,pb as g,qa as b,ra as v,sa as f,ua as H,va as D,vb as q,wa as S,xa as y,ya as r,za as s,zb as ee}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";function ve(o,e){if(o&1&&(w(),$(0,"path",1)(1,"path",2)),o&2){let t=u();b("d",t.fillD())("fill",t.color()),a(),b("d",t.pathD())("stroke",t.color())}}var T=class o{series=g([]);color=g("var(--accent)");height=g(200);hover=X();width=600;stats=p(()=>{let e=this.series();if(!e.length)return{max:1,min:0};let t=e.map(n=>n.cost);return{max:Math.max(...t,.01),min:0}});pathD=p(()=>{let e=this.series();if(!e.length)return"";let t=this.width,n=this.height(),{max:i}=this.stats();return e.map((l,m)=>{let x=m/Math.max(1,e.length-1)*t,h=n-l.cost/i*(n-20)-10;return(m===0?"M":"L")+x.toFixed(2)+" "+h.toFixed(2)}).join(" ")});fillD=p(()=>{let e=this.pathD();return e?e+` L ${this.width} ${this.height()} L 0 ${this.height()} Z`:""});onLeave(){this.hover.emit(null)}onMove(e){let n=e.currentTarget.getBoundingClientRect(),i=(e.clientX-n.left)/n.width,l=this.series();if(!l.length)return;let m=Math.min(l.length-1,Math.max(0,Math.round(i*(l.length-1)))),x=l[m];x&&this.hover.emit(x)}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-line-chart"]],inputs:{series:[1,"series"],color:[1,"color"],height:[1,"height"]},outputs:{hover:"hover"},decls:2,vars:3,consts:[["width","100%","preserveAspectRatio","none",1,"line-chart",3,"mousemove","mouseleave"],["opacity","0.10"],["fill","none","stroke-width","1.6","stroke-linecap","round","stroke-linejoin","round"]],template:function(t,n){t&1&&(w(),C(0,"svg",0),V("mousemove",function(l){return n.onMove(l)})("mouseleave",function(){return n.onLeave()}),v(1,ve,2,4),M()),t&2&&(b("viewBox","0 0 "+n.width+" "+n.height())("height",n.height()),a(),f(n.pathD()?1:-1))},styles:["[_nghost-%COMP%]{display:block}.line-chart[_ngcontent-%COMP%]{cursor:crosshair}"],changeDetection:0})};var fe=(o,e)=>e.label;function _e(o,e){if(o&1&&(w(),$(0,"path")),o&2){let t=e.$implicit;b("d",t.d)("fill",t.color)}}function xe(o,e){if(o&1&&(C(0,"div",3),c(1),M()),o&2){let t=u();a(),d(t.centerSub())}}var N=class o{data=g([]);size=g(150);centerLabel=g("");centerSub=g("");arcs=p(()=>{let e=this.data(),t=e.reduce((h,L)=>h+L.cost,0);if(t<=0)return[];let i=this.size()/2,l=i*.6,m=-Math.PI/2,x=[];for(let h of e){let L=h.cost/t*Math.PI*2,O=m+L,R=L>Math.PI?1:0,ce=i+Math.cos(m)*i,le=i+Math.sin(m)*i,de=i+Math.cos(O)*i,pe=i+Math.sin(O)*i,me=i+Math.cos(O)*l,ue=i+Math.sin(O)*l,ge=i+Math.cos(m)*l,he=i+Math.sin(m)*l;x.push({d:`M ${ce} ${le} A ${i} ${i} 0 ${R} 1 ${de} ${pe} L ${me} ${ue} A ${l} ${l} 0 ${R} 0 ${ge} ${he} Z`,color:h.color,label:h.short||h.model||""}),m=O}return x});static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-donut"]],inputs:{data:[1,"data"],size:[1,"size"],centerLabel:[1,"centerLabel"],centerSub:[1,"centerSub"]},decls:8,vars:9,consts:[[1,"donut"],[1,"donut-center"],[1,"center-label"],[1,"center-sub"]],template:function(t,n){t&1&&(C(0,"div",0),w(),C(1,"svg"),D(2,_e,1,2,":svg:path",null,fe),M(),A(),C(4,"div",1)(5,"div",2),c(6),M(),v(7,xe,2,1,"div",3),M()()),t&2&&(k("width",n.size(),"px")("height",n.size(),"px"),a(),b("width",n.size())("height",n.size())("viewBox","0 0 "+n.size()+" "+n.size()),a(),S(n.arcs()),a(4),d(n.centerLabel()),a(),f(n.centerSub()?7:-1))},styles:["[_nghost-%COMP%]{display:inline-block}.donut[_ngcontent-%COMP%]{position:relative}.donut-center[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.center-label[_ngcontent-%COMP%]{font-variant-numeric:tabular-nums;font-size:18px;font-weight:700;color:var(--text-primary)}.center-sub[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;margin-top:2px}"],changeDetection:0})};var be=()=>({value:"today",label:"Today"}),ye=()=>({value:"week",label:"This week"}),Ce=()=>({value:"month",label:"This month"}),Me=()=>({value:"all",label:"All time"}),we=(o,e,t,n)=>[o,e,t,n],Pe=()=>[0,1,2,3],De=(o,e)=>e.model,Se=(o,e)=>e.id;function ke(o,e){if(o&1&&_(0,"app-delta",10),o&2){let t=u();y("value",t.wowDelta())("invert",!0)}}function Ee(o,e){if(o&1&&(r(0,"div",11)(1,"div",24),c(2),s(),r(3,"div",25),c(4),s()()),o&2){let t=e,n=u();a(2),d(n.fmt$(t.cost)),a(2),Y("",t.prompts," prompts \xB7 day ",t.day)}}function Oe(o,e){if(o&1&&(r(0,"div",19),_(1,"span",26),r(2,"span",27),c(3),s(),r(4,"span",28),c(5),s(),r(6,"span",29),c(7),s()()),o&2){let t=e.$implicit,n=u();a(),k("background",t.color),a(2),d(t.short),a(2),d(n.fmt$(t.cost)),a(2),z("",n.percentOf(t.cost,n.total()),"%")}}function ze(o,e){o&1&&_(0,"div",30)}function Le(o,e){o&1&&D(0,ze,1,0,"div",30,H),o&2&&S(E(0,Pe))}function $e(o,e){if(o&1&&(r(0,"div",32)(1,"span",33),c(2),s(),r(3,"div",34)(4,"div",35),c(5),s(),r(6,"div",36),_(7,"span",37),s()(),r(8,"span",38),c(9),s(),r(10,"span",39),c(11),s(),r(12,"span",40),c(13),U(14,"number"),s(),r(15,"span",41),c(16),s()()),o&2){let t=e.$implicit,n=e.$index,i=u(2);K("first",n===0),a(2),d(n+1),a(3),d(t.text),a(2),k("width",t.cost_usd/i.maxPrompt()*100,"%")("background",t.cost_usd/i.maxPrompt()>.66?"var(--error)":"var(--accent)"),a(2),d(i.modelShort(t.model)),a(2),d(i.fmtK(i.promptTokens(t))),a(),k("color",i.cacheColor(i.cacheRate(t))),a(),z("",W(14,14,i.cacheRate(t)*100,"1.0-0"),"%"),a(3),d(i.fmt$(t.cost_usd))}}function Te(o,e){if(o&1&&D(0,$e,17,17,"div",31,Se),o&2){let t=u();S(t.topPrompts())}}var Ne={"claude-opus-4-7":"#A586F5","claude-opus-4":"#A586F5","claude-sonnet-4-6":"#5B93F2","claude-sonnet-4-7":"#5B93F2","claude-sonnet-4":"#5B93F2","claude-haiku-4-5":"#29D2BE","claude-haiku-4":"#29D2BE"},re={"claude-opus-4-7":"Opus 4.7","claude-opus-4":"Opus 4","claude-sonnet-4-6":"Sonnet 4.6","claude-sonnet-4-7":"Sonnet 4.7","claude-sonnet-4":"Sonnet 4","claude-haiku-4-5":"Haiku 4.5","claude-haiku-4":"Haiku 4"},se=class o{api=B(J);range=F("month");ranges=["today","week","month","all"];hovered=F(null);resource=Q(this.api,()=>`/api/claude/costs?range=${this.range()}`);series=p(()=>this.resource.state().data?.series??[]);topPrompts=p(()=>(this.resource.state().data?.topPrompts??[]).slice(0,12));maxPrompt=p(()=>{let e=this.topPrompts();return Math.max(.01,...e.map(t=>t.cost_usd??0))});byModel=p(()=>(this.resource.state().data?.byModel??[]).map(t=>({model:t.model,short:re[t.model]||t.model,cost:t.cost||0,color:Ne[t.model]||"#5C6573"})));total=p(()=>this.resource.state().data?.total??0);wowDelta=p(()=>this.resource.state().data?.wowDelta??0);setRange(e){this.range.set(e)}onHover(e){this.hovered.set(e)}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}cacheRate(e){let t=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return t>0?(e.cache_read_tokens??0)/t:0}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}modelShort(e){return e?re[e]||e.replace(/^claude-/,""):"?"}percentOf(e,t){return t>0?Math.round(e/t*100):0}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-costs"]],decls:34,vars:25,consts:[[1,"page","scroll-y"],["icon","dollar","title","Costs","sub","Where the money goes"],["actions",""],["size","sm",3,"change","value","options"],[1,"top-grid"],[1,"card","card-pad","chart-card"],[1,"chart-header"],[1,"big-number","mono"],[1,"row","gap-8",2,"margin-top","2px"],[1,"muted",2,"font-size","11.5px"],[3,"value","invert"],[2,"text-align","right"],["color","var(--accent)",3,"hover","series","height"],[1,"card","card-pad","donut-card"],[1,"row","gap-8",2,"align-self","flex-start","margin-bottom","8px"],["name","layers",2,"color","var(--node-code)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[3,"data","size","centerLabel","centerSub"],[1,"model-legend"],[1,"legend-row"],[1,"card","card-pad"],[1,"row","gap-8",2,"margin-bottom","12px"],["name","sortAsc",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px"],[1,"mono",2,"font-size","13px","font-weight","600"],[1,"muted",2,"font-size","10.5px"],[1,"swatch"],[1,"mono","grow",2,"font-size","11.5px"],[1,"mono",2,"font-size","11.5px"],[1,"mono","muted",2,"font-size","10.5px","width","38px","text-align","right"],[1,"skel","row-skel"],[1,"prompt-row",3,"first"],[1,"prompt-row"],[1,"mono","muted","tabular","rank"],[1,"prompt-grow"],[1,"prompt-text"],[1,"bar-track",2,"margin-top","4px","max-width","280px"],[1,"bar-fill"],[1,"mono","muted","prompt-model"],[1,"mono","muted","tabular","prompt-toks"],[1,"mono","tabular","cache-cell"],[1,"mono","tabular","cost-cell"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"app-page-head",1),j(2,2),r(3,"app-segmented",3),I("change",function(l){return n.setRange(l)}),s(),G(),s(),r(4,"div",4)(5,"div",5)(6,"div",6)(7,"div")(8,"div",7),c(9),s(),r(10,"div",8)(11,"span",9),c(12),s(),v(13,ke,1,2,"app-delta",10),s()(),v(14,Ee,5,3,"div",11),s(),r(15,"app-line-chart",12),I("hover",function(l){return n.onHover(l)}),s()(),r(16,"div",13)(17,"div",14),_(18,"app-icon",15),r(19,"span",16),c(20,"By model"),s()(),_(21,"app-donut",17),r(22,"div",18),D(23,Oe,8,5,"div",19,De),s()()(),r(25,"div",20)(26,"div",21),_(27,"app-icon",22),r(28,"span",16),c(29,"Most expensive prompts"),s(),r(30,"span",23),c(31),s()(),v(32,Le,2,1)(33,Te,2,0),s()()),t&2){let i;a(3),y("value",n.range())("options",Z(20,we,E(16,be),E(17,ye),E(18,Ce),E(19,Me))),a(6),d(n.fmt$(n.total())),a(3),z("total \xB7 ",n.range()),a(),f(n.range()!=="all"&&n.wowDelta()!==0?13:-1),a(),f((i=n.hovered())?14:-1,i),a(),y("series",n.series())("height",200),a(3),y("size",14),a(3),y("data",n.byModel())("size",150)("centerLabel","$"+n.total().toFixed(0))("centerSub",n.range()+" window"),a(2),S(n.byModel()),a(4),y("size",14),a(4),z("\xB7 top ",n.topPrompts().length),a(),f(n.resource.state().loading?32:33)}},dependencies:[T,N,te,ne,oe,ee,q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.card-pad[_ngcontent-%COMP%]{padding:14px}.top-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.3fr 1fr;gap:14px;margin-bottom:14px}.chart-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.chart-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:flex-start}.big-number[_ngcontent-%COMP%]{font-size:34px;font-weight:700;letter-spacing:-.02em}.donut-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:10px}.model-legend[_ngcontent-%COMP%]{width:100%;display:flex;flex-direction:column;gap:6px;margin-top:14px}.legend-row[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.swatch[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:3px;flex-shrink:0}.prompt-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:18px 1fr 70px 54px 44px 56px;gap:12px;align-items:center;padding:9px 0;border-top:1px solid var(--border-subtle)}.prompt-row.first[_ngcontent-%COMP%]{border-top:none}.rank[_ngcontent-%COMP%]{width:16px;font-size:11px}.prompt-grow[_ngcontent-%COMP%]{min-width:0}.prompt-text[_ngcontent-%COMP%]{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bar-track[_ngcontent-%COMP%]{height:4px;background:#ffffff0f;border-radius:999px;overflow:hidden}.bar-fill[_ngcontent-%COMP%]{display:block;height:100%;border-radius:999px}.prompt-model[_ngcontent-%COMP%]{font-size:10.5px;text-align:right}.prompt-toks[_ngcontent-%COMP%], .cache-cell[_ngcontent-%COMP%]{font-size:11px;text-align:right}.cost-cell[_ngcontent-%COMP%]{font-size:13px;font-weight:600;text-align:right}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.row-skel[_ngcontent-%COMP%]{height:30px;margin:6px 0}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{se as Costs};
1
+ import{a as oe}from"./chunk-MC4DFIHG.js";import{a as te}from"./chunk-UYC52MBC.js";import{a as ne}from"./chunk-SUZYBYDW.js";import{c as Q}from"./chunk-GR72OOCN.js";import"./chunk-7RNS77UP.js";import{a as J}from"./chunk-E44X4RH2.js";import{Aa as _,Ba as C,Ca as M,Da as $,Ea as j,Fa as G,I as B,Ia as I,Ja as V,Ka as u,O as w,P as A,Ta as k,Ua as K,Va as c,W as F,Wa as d,Xa as z,Ya as Y,bb as E,ea as a,fb as Z,gb as U,ib as W,ka as P,lb as p,ob as X,pb as g,qa as b,ra as v,sa as f,ua as H,va as D,vb as q,wa as S,xa as y,ya as r,za as s,zb as ee}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";function ve(o,e){if(o&1&&(w(),$(0,"path",1)(1,"path",2)),o&2){let t=u();b("d",t.fillD())("fill",t.color()),a(),b("d",t.pathD())("stroke",t.color())}}var T=class o{series=g([]);color=g("var(--accent)");height=g(200);hover=X();width=600;stats=p(()=>{let e=this.series();if(!e.length)return{max:1,min:0};let t=e.map(n=>n.cost);return{max:Math.max(...t,.01),min:0}});pathD=p(()=>{let e=this.series();if(!e.length)return"";let t=this.width,n=this.height(),{max:i}=this.stats();return e.map((l,m)=>{let x=m/Math.max(1,e.length-1)*t,h=n-l.cost/i*(n-20)-10;return(m===0?"M":"L")+x.toFixed(2)+" "+h.toFixed(2)}).join(" ")});fillD=p(()=>{let e=this.pathD();return e?e+` L ${this.width} ${this.height()} L 0 ${this.height()} Z`:""});onLeave(){this.hover.emit(null)}onMove(e){let n=e.currentTarget.getBoundingClientRect(),i=(e.clientX-n.left)/n.width,l=this.series();if(!l.length)return;let m=Math.min(l.length-1,Math.max(0,Math.round(i*(l.length-1)))),x=l[m];x&&this.hover.emit(x)}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-line-chart"]],inputs:{series:[1,"series"],color:[1,"color"],height:[1,"height"]},outputs:{hover:"hover"},decls:2,vars:3,consts:[["width","100%","preserveAspectRatio","none",1,"line-chart",3,"mousemove","mouseleave"],["opacity","0.10"],["fill","none","stroke-width","1.6","stroke-linecap","round","stroke-linejoin","round"]],template:function(t,n){t&1&&(w(),C(0,"svg",0),V("mousemove",function(l){return n.onMove(l)})("mouseleave",function(){return n.onLeave()}),v(1,ve,2,4),M()),t&2&&(b("viewBox","0 0 "+n.width+" "+n.height())("height",n.height()),a(),f(n.pathD()?1:-1))},styles:["[_nghost-%COMP%]{display:block}.line-chart[_ngcontent-%COMP%]{cursor:crosshair}"],changeDetection:0})};var fe=(o,e)=>e.label;function _e(o,e){if(o&1&&(w(),$(0,"path")),o&2){let t=e.$implicit;b("d",t.d)("fill",t.color)}}function xe(o,e){if(o&1&&(C(0,"div",3),c(1),M()),o&2){let t=u();a(),d(t.centerSub())}}var N=class o{data=g([]);size=g(150);centerLabel=g("");centerSub=g("");arcs=p(()=>{let e=this.data(),t=e.reduce((h,L)=>h+L.cost,0);if(t<=0)return[];let i=this.size()/2,l=i*.6,m=-Math.PI/2,x=[];for(let h of e){let L=h.cost/t*Math.PI*2,O=m+L,R=L>Math.PI?1:0,ce=i+Math.cos(m)*i,le=i+Math.sin(m)*i,de=i+Math.cos(O)*i,pe=i+Math.sin(O)*i,me=i+Math.cos(O)*l,ue=i+Math.sin(O)*l,ge=i+Math.cos(m)*l,he=i+Math.sin(m)*l;x.push({d:`M ${ce} ${le} A ${i} ${i} 0 ${R} 1 ${de} ${pe} L ${me} ${ue} A ${l} ${l} 0 ${R} 0 ${ge} ${he} Z`,color:h.color,label:h.short||h.model||""}),m=O}return x});static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-donut"]],inputs:{data:[1,"data"],size:[1,"size"],centerLabel:[1,"centerLabel"],centerSub:[1,"centerSub"]},decls:8,vars:9,consts:[[1,"donut"],[1,"donut-center"],[1,"center-label"],[1,"center-sub"]],template:function(t,n){t&1&&(C(0,"div",0),w(),C(1,"svg"),D(2,_e,1,2,":svg:path",null,fe),M(),A(),C(4,"div",1)(5,"div",2),c(6),M(),v(7,xe,2,1,"div",3),M()()),t&2&&(k("width",n.size(),"px")("height",n.size(),"px"),a(),b("width",n.size())("height",n.size())("viewBox","0 0 "+n.size()+" "+n.size()),a(),S(n.arcs()),a(4),d(n.centerLabel()),a(),f(n.centerSub()?7:-1))},styles:["[_nghost-%COMP%]{display:inline-block}.donut[_ngcontent-%COMP%]{position:relative}.donut-center[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.center-label[_ngcontent-%COMP%]{font-variant-numeric:tabular-nums;font-size:18px;font-weight:700;color:var(--text-primary)}.center-sub[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;margin-top:2px}"],changeDetection:0})};var be=()=>({value:"today",label:"Today"}),ye=()=>({value:"week",label:"This week"}),Ce=()=>({value:"month",label:"This month"}),Me=()=>({value:"all",label:"All time"}),we=(o,e,t,n)=>[o,e,t,n],Pe=()=>[0,1,2,3],De=(o,e)=>e.model,Se=(o,e)=>e.id;function ke(o,e){if(o&1&&_(0,"app-delta",10),o&2){let t=u();y("value",t.wowDelta())("invert",!0)}}function Ee(o,e){if(o&1&&(r(0,"div",11)(1,"div",24),c(2),s(),r(3,"div",25),c(4),s()()),o&2){let t=e,n=u();a(2),d(n.fmt$(t.cost)),a(2),Y("",t.prompts," prompts \xB7 day ",t.day)}}function Oe(o,e){if(o&1&&(r(0,"div",19),_(1,"span",26),r(2,"span",27),c(3),s(),r(4,"span",28),c(5),s(),r(6,"span",29),c(7),s()()),o&2){let t=e.$implicit,n=u();a(),k("background",t.color),a(2),d(t.short),a(2),d(n.fmt$(t.cost)),a(2),z("",n.percentOf(t.cost,n.total()),"%")}}function ze(o,e){o&1&&_(0,"div",30)}function Le(o,e){o&1&&D(0,ze,1,0,"div",30,H),o&2&&S(E(0,Pe))}function $e(o,e){if(o&1&&(r(0,"div",32)(1,"span",33),c(2),s(),r(3,"div",34)(4,"div",35),c(5),s(),r(6,"div",36),_(7,"span",37),s()(),r(8,"span",38),c(9),s(),r(10,"span",39),c(11),s(),r(12,"span",40),c(13),U(14,"number"),s(),r(15,"span",41),c(16),s()()),o&2){let t=e.$implicit,n=e.$index,i=u(2);K("first",n===0),a(2),d(n+1),a(3),d(t.text),a(2),k("width",t.cost_usd/i.maxPrompt()*100,"%")("background",t.cost_usd/i.maxPrompt()>.66?"var(--error)":"var(--accent)"),a(2),d(i.modelShort(t.model)),a(2),d(i.fmtK(i.promptTokens(t))),a(),k("color",i.cacheColor(i.cacheRate(t))),a(),z("",W(14,14,i.cacheRate(t)*100,"1.0-0"),"%"),a(3),d(i.fmt$(t.cost_usd))}}function Te(o,e){if(o&1&&D(0,$e,17,17,"div",31,Se),o&2){let t=u();S(t.topPrompts())}}var Ne={"claude-opus-4-7":"#A586F5","claude-opus-4":"#A586F5","claude-sonnet-4-6":"#5B93F2","claude-sonnet-4-7":"#5B93F2","claude-sonnet-4":"#5B93F2","claude-haiku-4-5":"#29D2BE","claude-haiku-4":"#29D2BE"},re={"claude-opus-4-7":"Opus 4.7","claude-opus-4":"Opus 4","claude-sonnet-4-6":"Sonnet 4.6","claude-sonnet-4-7":"Sonnet 4.7","claude-sonnet-4":"Sonnet 4","claude-haiku-4-5":"Haiku 4.5","claude-haiku-4":"Haiku 4"},se=class o{api=B(J);range=F("month");ranges=["today","week","month","all"];hovered=F(null);resource=Q(this.api,()=>`/api/claude/costs?range=${this.range()}`);series=p(()=>this.resource.state().data?.series??[]);topPrompts=p(()=>(this.resource.state().data?.topPrompts??[]).slice(0,12));maxPrompt=p(()=>{let e=this.topPrompts();return Math.max(.01,...e.map(t=>t.cost_usd??0))});byModel=p(()=>(this.resource.state().data?.byModel??[]).map(t=>({model:t.model,short:re[t.model]||t.model,cost:t.cost||0,color:Ne[t.model]||"#5C6573"})));total=p(()=>this.resource.state().data?.total??0);wowDelta=p(()=>this.resource.state().data?.wowDelta??0);setRange(e){this.range.set(e)}onHover(e){this.hovered.set(e)}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}cacheRate(e){let t=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return t>0?(e.cache_read_tokens??0)/t:0}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}modelShort(e){return e?re[e]||e.replace(/^claude-/,""):"?"}percentOf(e,t){return t>0?Math.round(e/t*100):0}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=P({type:o,selectors:[["app-costs"]],decls:34,vars:25,consts:[[1,"page","scroll-y"],["icon","dollar","title","Costs","sub","Where the money goes"],["actions",""],["size","sm",3,"change","value","options"],[1,"top-grid"],[1,"card","card-pad","chart-card"],[1,"chart-header"],[1,"big-number","mono"],[1,"row","gap-8",2,"margin-top","2px"],[1,"muted",2,"font-size","11.5px"],[3,"value","invert"],[2,"text-align","right"],["color","var(--accent)",3,"hover","series","height"],[1,"card","card-pad","donut-card"],[1,"row","gap-8",2,"align-self","flex-start","margin-bottom","8px"],["name","layers",2,"color","var(--node-code)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[3,"data","size","centerLabel","centerSub"],[1,"model-legend"],[1,"legend-row"],[1,"card","card-pad"],[1,"row","gap-8",2,"margin-bottom","12px"],["name","sortAsc",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px"],[1,"mono",2,"font-size","13px","font-weight","600"],[1,"muted",2,"font-size","10.5px"],[1,"swatch"],[1,"mono","grow",2,"font-size","11.5px"],[1,"mono",2,"font-size","11.5px"],[1,"mono","muted",2,"font-size","10.5px","width","38px","text-align","right"],[1,"skel","row-skel"],[1,"prompt-row",3,"first"],[1,"prompt-row"],[1,"mono","muted","tabular","rank"],[1,"prompt-grow"],[1,"prompt-text"],[1,"bar-track",2,"margin-top","4px","max-width","280px"],[1,"bar-fill"],[1,"mono","muted","prompt-model"],[1,"mono","muted","tabular","prompt-toks"],[1,"mono","tabular","cache-cell"],[1,"mono","tabular","cost-cell"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"app-page-head",1),j(2,2),r(3,"app-segmented",3),I("change",function(l){return n.setRange(l)}),s(),G(),s(),r(4,"div",4)(5,"div",5)(6,"div",6)(7,"div")(8,"div",7),c(9),s(),r(10,"div",8)(11,"span",9),c(12),s(),v(13,ke,1,2,"app-delta",10),s()(),v(14,Ee,5,3,"div",11),s(),r(15,"app-line-chart",12),I("hover",function(l){return n.onHover(l)}),s()(),r(16,"div",13)(17,"div",14),_(18,"app-icon",15),r(19,"span",16),c(20,"By model"),s()(),_(21,"app-donut",17),r(22,"div",18),D(23,Oe,8,5,"div",19,De),s()()(),r(25,"div",20)(26,"div",21),_(27,"app-icon",22),r(28,"span",16),c(29,"Most expensive prompts"),s(),r(30,"span",23),c(31),s()(),v(32,Le,2,1)(33,Te,2,0),s()()),t&2){let i;a(3),y("value",n.range())("options",Z(20,we,E(16,be),E(17,ye),E(18,Ce),E(19,Me))),a(6),d(n.fmt$(n.total())),a(3),z("total \xB7 ",n.range()),a(),f(n.range()!=="all"&&n.wowDelta()!==0?13:-1),a(),f((i=n.hovered())?14:-1,i),a(),y("series",n.series())("height",200),a(3),y("size",14),a(3),y("data",n.byModel())("size",150)("centerLabel","$"+n.total().toFixed(0))("centerSub",n.range()+" window"),a(2),S(n.byModel()),a(4),y("size",14),a(4),z("\xB7 top ",n.topPrompts().length),a(),f(n.resource.state().loading?32:33)}},dependencies:[T,N,te,ne,oe,ee,q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.card-pad[_ngcontent-%COMP%]{padding:14px}.top-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.3fr 1fr;gap:14px;margin-bottom:14px}.chart-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.chart-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:flex-start}.big-number[_ngcontent-%COMP%]{font-size:34px;font-weight:700;letter-spacing:-.02em}.donut-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:10px}.model-legend[_ngcontent-%COMP%]{width:100%;display:flex;flex-direction:column;gap:6px;margin-top:14px}.legend-row[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.swatch[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:3px;flex-shrink:0}.prompt-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:18px 1fr 70px 54px 44px 56px;gap:12px;align-items:center;padding:9px 0;border-top:1px solid var(--border-subtle)}.prompt-row.first[_ngcontent-%COMP%]{border-top:none}.rank[_ngcontent-%COMP%]{width:16px;font-size:11px}.prompt-grow[_ngcontent-%COMP%]{min-width:0}.prompt-text[_ngcontent-%COMP%]{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bar-track[_ngcontent-%COMP%]{height:4px;background:#ffffff0f;border-radius:999px;overflow:hidden}.bar-fill[_ngcontent-%COMP%]{display:block;height:100%;border-radius:999px}.prompt-model[_ngcontent-%COMP%]{font-size:10.5px;text-align:right}.prompt-toks[_ngcontent-%COMP%], .cache-cell[_ngcontent-%COMP%]{font-size:11px;text-align:right}.cost-cell[_ngcontent-%COMP%]{font-size:13px;font-weight:600;text-align:right}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.row-skel[_ngcontent-%COMP%]{height:30px;margin:6px 0}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{se as Costs};
@@ -0,0 +1,2 @@
1
+ import{a as A,b as q,c as W}from"./chunk-T66XVKGB.js";import{a as Q}from"./chunk-DTRN7FZR.js";import{a as Y}from"./chunk-MC4DFIHG.js";import{a as K}from"./chunk-UYC52MBC.js";import{a as J}from"./chunk-2GBEK2GM.js";import{a as U}from"./chunk-SUZYBYDW.js";import{a as L,c as b}from"./chunk-GR72OOCN.js";import{c as G,d as B}from"./chunk-SHPTC4RL.js";import{a as V}from"./chunk-7RNS77UP.js";import{a as j}from"./chunk-E44X4RH2.js";import{Aa as l,Ga as P,I as w,Ia as v,Ka as c,M as f,N as C,Ta as E,Ua as y,Va as s,W as R,Wa as S,Xa as _,Ya as D,bb as N,ea as r,gb as O,ib as z,ka as F,lb as m,ra as u,sa as g,ua as I,va as M,vb as $,wa as T,xa as p,ya as a,za as o,zb as H}from"./chunk-PDN6QYGJ.js";import"./chunk-Q7L6LLAK.js";var ee=()=>[0,1,2,3],te=()=>[0,1,2,3,4],Z=(i,e)=>e.id;function ne(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.fmt$(n.lastSessionCostStat().value)," ")}}function ie(i,e){i&1&&s(0," \xA0 ")}function ae(i,e){if(i&1&&l(0,"app-sparkline",11),i&2){let n=c();p("data",n.lastSessionCostStat().series)("width",64)("height",22)("fill",!0)}}function oe(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.lastSessionCostStat().delta)("invert",!0)}}function re(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.toolCallsStat().value.toLocaleString()," ")}}function se(i,e){i&1&&s(0," \xA0 ")}function le(i,e){if(i&1&&l(0,"app-sparkline",14),i&2){let n=c();p("data",n.toolCallsStat().series)("width",64)("height",22)("fill",!0)}}function de(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.toolCallsStat().delta)("invert",!0)}}function pe(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.subagentPctStat().value,"% ")}}function ce(i,e){i&1&&s(0," \xA0 ")}function me(i,e){if(i&1&&l(0,"app-sparkline",16),i&2){let n=c();p("data",n.subagentPctStat().series)("width",64)("height",22)("fill",!0)}}function ue(i,e){if(i&1&&l(0,"app-delta",12),i&2){let n=c();p("value",n.subagentPctStat().delta)("invert",!0)}}function ge(i,e){if(i&1&&s(0),i&2){let n=c();_(" ",n.driftStat().value," ")}}function he(i,e){i&1&&s(0," \xA0 ")}function ve(i,e){i&1&&(a(0,"span",24),s(1,"seed"),o())}function _e(i,e){if(i&1&&(a(0,"span",31),s(1),o()),i&2){let n=c();r(),_(" ",n.urgentTipCount()," urgent ")}}function be(i,e){i&1&&l(0,"div",58)}function xe(i,e){i&1&&M(0,be,1,0,"div",58,I),i&2&&T(N(0,ee))}function fe(i,e){i&1&&(a(0,"div",34),s(1,"No tips yet. Run more sessions to populate."),o())}function Ce(i,e){if(i&1&&(a(0,"code",66),s(1),o()),i&2){let n=c().$implicit;r(),S(n.fix)}}function ye(i,e){if(i&1&&(a(0,"span",73),s(1),o()),i&2){let n=c().$implicit,t=c(2);E("color",t.tipSevColor(n.severity)),r(),S(n.saving)}}function Se(i,e){if(i&1){let n=P();a(0,"div",60)(1,"div",61),l(2,"app-icon",62),o(),a(3,"div",63)(4,"div",64),s(5),o(),a(6,"div",65),u(7,Ce,2,1,"code",66),l(8,"span",67),u(9,ye,2,3,"span",68),o()(),a(10,"div",69)(11,"button",70),v("click",function(){f(n);let d=c(2);return C(d.go("tips"))}),s(12,"Apply"),o(),a(13,"button",71),v("click",function(){let d=f(n).$implicit,h=c(2);return C(h.dismissTip(d.id))}),l(14,"app-icon",72),o()()()}if(i&2){let n=e.$implicit,t=c(2);E("border-left-color",t.tipSevColor(n.severity)),r(),E("color",t.tipSevColor(n.severity)),r(),p("name",t.tipIcon(n))("size",14),r(3),S(n.title),r(2),g(n.fix?7:-1),r(2),g(n.saving?9:-1),r(5),p("size",12)}}function ke(i,e){if(i&1&&M(0,Se,15,10,"div",59,Z),i&2){let n=c();T(n.visibleTips())}}function we(i,e){i&1&&l(0,"div",42)}function Me(i,e){i&1&&(a(0,"div",43),s(1," No tool calls in the selected window. "),o())}function Te(i,e){if(i&1){let n=P();a(0,"app-treemap",74),v("pick",function(){f(n);let d=c();return C(d.go("heatmap"))}),o()}if(i&2){let n=c();p("items",n.treemapItems())("height",116)("selKey",null)}}function Ee(i,e){i&1&&l(0,"div",75)}function Pe(i,e){i&1&&M(0,Ee,1,0,"div",75,I),i&2&&T(N(0,te))}function De(i,e){i&1&&(a(0,"div",34),s(1,"No prompts ingested for this range."),o())}function Oe(i,e){i&1&&l(0,"app-icon",80),i&2&&p("size",11)}function ze(i,e){if(i&1){let n=P();a(0,"div",77),v("click",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.enter",function(){f(n);let d=c(2);return C(d.go("sessions"))})("keydown.space",function(){f(n);let d=c(2);return C(d.go("sessions"))}),a(1,"div",78)(2,"div",79),u(3,Oe,1,1,"app-icon",80),s(4),o(),a(5,"div",81),l(6,"app-bar",82),o()(),a(7,"div",83)(8,"div",84),s(9),o(),a(10,"div",85),s(11),O(12,"number"),o()()()}if(i&2){let n=e.$implicit,t=c(2);r(3),g(n.is_sidechain?3:-1),r(),_(" ",n.text||"(no text)"," "),r(2),p("frac",t.promptFrac(n.cost_usd))("color",t.promptBarColor(n.cost_usd))("height",4),r(2),E("color",n.cost_usd/t.maxPromptCost()>.7?"var(--error)":"var(--text-primary)"),y("expensive",n.cost_usd/t.maxPromptCost()>.7),r(),_(" ",t.fmt$(n.cost_usd)," "),r(2),D(" ",t.fmtK(t.promptTotalTokens(n))," \xB7 ",z(12,12,t.promptCacheRate(n)*100,"1.0-0"),"% ")}}function Re(i,e){if(i&1&&M(0,ze,13,15,"div",76,Z),i&2){let n=c();T(n.topPrompts())}}function Ie(i,e){i&1&&l(0,"div",56)}function Ne(i,e){if(i&1&&(a(0,"div",86)(1,"div",87),s(2),O(3,"number"),o(),a(4,"div",88)(5,"div",40),s(6,"cache read rate"),o(),l(7,"app-delta",12),o()(),l(8,"div",89),a(9,"div",90)(10,"div",91)(11,"div",92),s(12,"Creation tokens"),o(),a(13,"div",93),s(14),o(),a(15,"div",94),s(16,"ephemeral"),o()(),a(17,"div",91)(18,"div",92),s(19,"Read tokens"),o(),a(20,"div",93),s(21),o(),a(22,"div",94),s(23,"charged at ~10%"),o()(),a(24,"div",91)(25,"div",92),s(26,"Saved this week"),o(),a(27,"div",95),s(28),o(),a(29,"div",94),s(30,"vs no cache"),o()(),a(31,"div",91)(32,"div",92),s(33,"WoW"),o(),a(34,"div",95),s(35),O(36,"number"),o(),a(37,"div",94),s(38,"more reuse"),o()()()),i&2){let n=c(),t=n.cache.state().data;r(2),_("",z(3,8,t.readRate*100,"1.0-0"),"%"),r(5),p("value",t.wowDelta)("invert",!1),r(7),S(n.fmtK(t.creationTokens)),r(7),S(n.fmtK(t.readTokens)),r(7),S(n.fmt$(t.dollarsSaved)),r(7),D(" ",t.wowDelta>=0?"+":"","",z(36,11,t.wowDelta*100,"1.0-0"),"% ")}}var X=class i{api=w(j);router=w(G);projects=w(V);conn=w(L);range=R("week");rangeOptions=[{value:"today",label:"Today"},{value:"week",label:"This week"},{value:"month",label:"This month"},{value:"all",label:"All time"}];status=b(this.api,()=>`/api/status${this.projects.projectQuery()}`);miniGraphSearch=b(this.api,()=>`/api/graph/search?q=on&limit=18${this.projects.projectQuery("&")}`);tips=b(this.api,()=>"/api/claude/tips");heatmap=b(this.api,()=>`/api/claude/heatmap?range=${this.range()}`);costs=b(this.api,()=>`/api/claude/costs?range=${this.range()}`);cache=b(this.api,()=>`/api/claude/cache?range=${this.range()}`);sessions=b(this.api,()=>`/api/claude/sessions?range=${this.range()}&limit=10`);stats=b(this.api,()=>`/api/claude/stats?range=${this.range()}`);EMPTY_METRIC={value:0,delta:0,series:[]};lastSessionCostStat=m(()=>this.stats.state().data?.lastSessionCost??this.EMPTY_METRIC);toolCallsStat=m(()=>this.stats.state().data?.toolCalls??this.EMPTY_METRIC);subagentPctStat=m(()=>this.stats.state().data?.subagentPct??this.EMPTY_METRIC);driftStat=m(()=>this.stats.state().data?.drift??this.EMPTY_METRIC);lastSession=m(()=>(this.sessions.state().data?.sessions??[])[0]??null);lastSessionCost=m(()=>this.lastSession()?.total_cost_usd??0);toolCallCount=m(()=>(this.heatmap.state().data?.tools??[]).reduce((n,t)=>n+(t.calls??0),0));subagentShare=m(()=>{let e=this.heatmap.state().data?.subagents??[],n=e.find(x=>x.type==="subagent"),t=e.find(x=>x.type==="main"),d=n?.cost??0,h=t?.cost??0,k=d+h;return k>0?Math.round(d/k*100):0});driftCount=m(()=>this.status.state().data?.drift??0);nodeCountLabel=m(()=>this.status.state().data?.nodeCount??0);urgentTipCount=m(()=>(this.tips.state().data?.tips??[]).filter(n=>n.severity==="error").length);dismissedTips=R(new Set);dismissTip(e){this.dismissedTips.update(n=>{let t=new Set(n);return t.add(e),t})}isTipDismissed(e){return this.dismissedTips().has(e)}visibleTips=m(()=>{let e=this.dismissedTips();return(this.tips.state().data?.tips??[]).filter(n=>!e.has(n.id)).slice(0,4)});treemapItems=m(()=>{let e=(this.heatmap.state().data?.files??[]).slice(0,30);if(!e.length)return[];let n=Math.max(1,...e.map(t=>t.resultBytes&&t.calls?t.resultBytes/t.calls:0));return e.map(t=>{let d=t.calls>0?t.resultBytes/t.calls:0,h=Math.min(1,d/n);return{key:t.path,label:A(t.path),value:t.calls,intensity:h,sub:t.calls+" calls",title:`${t.path}
2
+ ${t.calls} calls \xB7 ${this.fmtK(Math.round(d))}/call`}})});topPrompts=m(()=>(this.costs.state().data?.topPrompts??[]).slice(0,8));maxPromptCost=m(()=>Math.max(.01,...this.topPrompts().map(e=>e.cost_usd??0)));rangeTotal=m(()=>(this.costs.state().data?.series??[]).reduce((n,t)=>n+(t.cost??0),0));liveSource=m(()=>this.conn.online()?"live":"offline");miniGraphSource=m(()=>(this.miniGraphSearch.state().data?.results?.length??0)>0?"api":"seed");miniGraphNodes=m(()=>{let e=this.miniGraphSearch.state().data?.results??[];return e.length>0?Ge(e.slice(0,18).map(n=>({id:n.node.id,label:n.node.name,sub:n.node.filePath?.split("/").slice(-2).join("/"),kind:n.node.kind}))):Fe});miniGraphEdges=m(()=>{if(this.miniGraphSource()==="api"){let e=this.miniGraphNodes(),n=[];for(let t=1;t<e.length;t++){let d=e[Math.floor(Math.random()*t)],h=e[t];d&&h&&n.push({from:d.id,to:h.id,kind:"calls"})}return n}return $e});onMiniGraphPick(e){this.router.navigate(["/graph"],{queryParams:{focus:e}})}setRange(e){this.range.set(e)}go(e){this.router.navigate(["/"+e])}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e6?(e/1e6).toFixed(1)+"M":e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptCacheRate(e){let n=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return n>0?(e.cache_read_tokens??0)/n:0}promptTotalTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}promptBarColor(e){return e/this.maxPromptCost()>.7?"var(--error)":"var(--accent)"}promptFrac(e){return Math.max(0,Math.min(1,e/this.maxPromptCost()))}tipSevColor(e){return e==="error"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)"}tipIcon(e){return e.icon?e.icon:e.severity==="error"?"cancel":e.severity==="warn"?"warn":"info"}static \u0275fac=function(n){return new(n||i)};static \u0275cmp=F({type:i,selectors:[["app-dashboard"]],decls:122,vars:48,consts:[[1,"scroll-y","dashboard"],["icon","dashboard","title","Dashboard",3,"sub"],["actions",""],["size","sm",3,"change","options","value"],[1,"stat-grid"],["type","button",1,"stat-tile",3,"click"],[1,"row","gap-8","stat-eyebrow"],["name","coins",2,"color","var(--accent)",3,"size"],[1,"eyebrow",2,"letter-spacing","0.04em"],[1,"row","stat-value-row"],[1,"stat-value","tabular"],["color","var(--accent)",3,"data","width","height","fill"],[3,"value","invert"],["name","wrench",2,"color","var(--node-spec)",3,"size"],["color","var(--node-spec)",3,"data","width","height","fill"],["name","bot",2,"color","var(--node-code)",3,"size"],["color","var(--node-code)",3,"data","width","height","fill"],["name","drift",2,"color","var(--warn)",3,"size"],[1,"center-grid"],[1,"card","graph-card"],[1,"card-head"],[1,"card-title","row","gap-8"],["name","graph",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px","font-weight","400"],["title","No graph data yet \u2014 illustrative",1,"pill","seed-pill"],["routerLink","/graph",1,"btn","btn-ghost","btn-xs"],["name","arrowRight",3,"size"],[1,"mini-graph"],[3,"nodeClick","nodes","edges"],[1,"card","tips-card"],["name","tips",2,"color","var(--warn)",3,"size"],[1,"pill",2,"font-size","10px","background","var(--error-soft)","color","var(--error)"],["routerLink","/tips",1,"btn","btn-ghost","btn-xs"],[1,"scroll-y","tips-body"],[1,"tip-empty"],[1,"card","card-pad","heatmap-card"],[1,"row","heatmap-head"],[1,"row","gap-8"],["name","flame",2,"color","var(--warn)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[1,"muted",2,"font-size","11px"],["routerLink","/heatmap",1,"btn","btn-ghost","btn-xs"],[1,"skel",2,"height","116px","border-radius","7px"],[1,"tip-empty",2,"height","116px","display","grid","place-items","center"],[3,"items","height","selKey"],[1,"row","gap-10","heatmap-legend"],[1,"muted",2,"font-size","10px"],[1,"heatmap-gradient"],[1,"muted",2,"font-size","9.5px"],[1,"bottom-grid"],[1,"card","card-pad","prompts-card"],[1,"row","prompts-head"],["routerLink","/costs",1,"btn","btn-ghost","btn-xs"],[1,"col"],[1,"card","card-pad","cache-card"],["name","database",2,"color","var(--node-route)",3,"size"],[1,"skel",2,"height","70px","border-radius","5px"],[1,"dash-footer","mono","muted"],[1,"skel",2,"height","64px","border-radius","8px"],[1,"tip-row",3,"border-left-color"],[1,"tip-row"],[1,"tip-sev-icon"],[3,"name","size"],[1,"grow","tip-body-col",2,"min-width","0"],[1,"tip-title"],[1,"row","gap-8","tip-meta-row"],[1,"mono","tip-fix"],[1,"grow"],[1,"pill",2,"font-size","10px","color","inherit","background","transparent",3,"color"],[1,"row","gap-4",2,"flex-shrink","0"],["type","button",1,"btn","btn-secondary","btn-xs",3,"click"],["type","button","title","Dismiss",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"pill",2,"font-size","10px","color","inherit","background","transparent"],[3,"pick","items","height","selKey"],[1,"skel",2,"height","26px","margin","4px 0","border-radius","4px"],["role","button","tabindex","0",1,"prompt-row"],["role","button","tabindex","0",1,"prompt-row",3,"click","keydown.enter","keydown.space"],[1,"grow","prompt-left",2,"min-width","0"],[1,"prompt-text"],["name","bot",2,"color","var(--node-code)","margin-right","5px","vertical-align","-1px",3,"size"],[2,"margin-top","4px","width","70%"],[3,"frac","color","height"],[1,"prompt-right"],[1,"mono","tabular","prompt-cost"],[1,"mono","muted",2,"font-size","10px"],[1,"row","cache-headline"],[1,"tabular","cache-rate"],[2,"padding-bottom","3px"],[1,"cache-divider"],[1,"cache-kv-grid"],[1,"kv"],[1,"kv-label"],[1,"kv-value","mono","tabular"],[1,"kv-sub","mono","muted"],[1,"kv-value","mono","tabular",2,"color","var(--success)"]],template:function(n,t){n&1&&(a(0,"div",0)(1,"app-page-head",1)(2,"div",2)(3,"app-segmented",3),v("change",function(h){return t.setRange(h)}),o()()(),a(4,"div",4)(5,"button",5),v("click",function(){return t.go("sessions")}),a(6,"div",6),l(7,"app-icon",7),a(8,"span",8),s(9,"Last session cost"),o()(),a(10,"div",9)(11,"div",10),u(12,ne,1,1)(13,ie,1,0),o(),u(14,ae,1,4,"app-sparkline",11),o(),u(15,oe,1,2,"app-delta",12),o(),a(16,"button",5),v("click",function(){return t.go("heatmap")}),a(17,"div",6),l(18,"app-icon",13),a(19,"span",8),s(20),o()(),a(21,"div",9)(22,"div",10),u(23,re,1,1)(24,se,1,0),o(),u(25,le,1,4,"app-sparkline",14),o(),u(26,de,1,2,"app-delta",12),o(),a(27,"button",5),v("click",function(){return t.go("heatmap")}),a(28,"div",6),l(29,"app-icon",15),a(30,"span",8),s(31,"Subagent spend"),o()(),a(32,"div",9)(33,"div",10),u(34,pe,1,1)(35,ce,1,0),o(),u(36,me,1,4,"app-sparkline",16),o(),u(37,ue,1,2,"app-delta",12),o(),a(38,"button",5),v("click",function(){return t.go("drift")}),a(39,"div",6),l(40,"app-icon",17),a(41,"span",8),s(42,"Drift queue"),o()(),a(43,"div",9)(44,"div",10),u(45,ge,1,1)(46,he,1,0),o()()()(),a(47,"div",18)(48,"div",19)(49,"div",20)(50,"div",21),l(51,"app-icon",22),a(52,"span"),s(53,"Recent neighborhood"),o(),a(54,"span",23),s(55,"\xB7 last edited files"),o(),u(56,ve,2,0,"span",24),o(),a(57,"a",25),s(58," Open graph "),l(59,"app-icon",26),o()(),a(60,"div",27)(61,"app-graph-canvas",28),v("nodeClick",function(h){return t.onMiniGraphPick(h)}),o()()(),a(62,"div",29)(63,"div",20)(64,"div",21),l(65,"app-icon",30),a(66,"span"),s(67,"Tips"),o(),u(68,_e,2,1,"span",31),o(),a(69,"a",32),s(70,"All"),o()(),a(71,"div",33),u(72,xe,2,1)(73,fe,2,0,"div",34)(74,ke,2,0),o()()(),a(75,"div",35)(76,"div",36)(77,"div",37),l(78,"app-icon",38),a(79,"span",39),s(80,"Tool-call heatmap"),o(),a(81,"span",40),s(82,"\xB7 area = calls, color = tokens / call"),o()(),a(83,"a",41),s(84," Open heatmap "),l(85,"app-icon",26),o()(),u(86,we,1,0,"div",42)(87,Me,2,0,"div",43)(88,Te,1,3,"app-treemap",44),a(89,"div",45)(90,"span",46),s(91,"tokens / call"),o(),l(92,"div",47),a(93,"span",48),s(94,"efficient \u2192 wasteful"),o()()(),a(95,"div",49)(96,"div",50)(97,"div",51)(98,"div",37),l(99,"app-icon",7),a(100,"span",39),s(101,"Recent prompts"),o(),a(102,"span",40),s(103,"\xB7 by cost"),o()(),a(104,"a",52),s(105,"Cost ranking"),o()(),a(106,"div",53),u(107,Pe,2,1)(108,De,2,0,"div",34)(109,Re,2,0),o()(),a(110,"div",54)(111,"div",37),l(112,"app-icon",55),a(113,"span",39),s(114,"Cache analytics"),o()(),u(115,Ie,1,0,"div",56)(116,Ne,39,14),o()(),a(117,"footer",57),s(118),a(119,"span"),s(120,"\u25CF"),o(),s(121),o()()),n&2&&(r(),p("sub","specship \xB7 "+t.nodeCountLabel().toLocaleString()+" nodes \xB7 last session "+t.fmt$(t.lastSessionCost())),r(2),p("options",t.rangeOptions)("value",t.range()),r(4),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?13:12),r(2),g(t.lastSessionCostStat().series.length>0?14:-1),r(),g(t.lastSessionCostStat().delta!==0?15:-1),r(3),p("size",13),r(2),_("Tool calls \xB7 ",t.range()),r(2),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?24:23),r(2),g(t.toolCallsStat().series.length>0?25:-1),r(),g(t.toolCallsStat().delta!==0?26:-1),r(3),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?35:34),r(2),g(t.subagentPctStat().series.length>0?36:-1),r(),g(t.subagentPctStat().delta!==0?37:-1),r(3),p("size",13),r(4),y("skel",t.stats.state().loading),r(),g(t.stats.state().loading?46:45),r(6),p("size",14),r(5),g(t.miniGraphSource()==="seed"?56:-1),r(3),p("size",11),r(2),p("nodes",t.miniGraphNodes())("edges",t.miniGraphEdges()),r(4),p("size",14),r(3),g(t.urgentTipCount()>0?68:-1),r(4),g(t.tips.state().loading?72:t.visibleTips().length===0?73:74),r(6),p("size",14),r(7),p("size",11),r(),g(t.heatmap.state().loading?86:t.treemapItems().length===0?87:88),r(13),p("size",14),r(8),g(t.costs.state().loading?107:t.topPrompts().length===0?108:109),r(5),p("size",14),r(3),g(t.cache.state().loading?115:t.cache.state().data?116:-1),r(3),D(" ",t.range()," window total: ",t.fmt$(t.rangeTotal())," \xB7 "),r(),y("dot-live",t.liveSource()==="live")("dot-mock",t.liveSource()==="offline"),r(2),_(" ",t.liveSource()==="live"?"Live":"Offline"," "))},dependencies:[B,H,K,U,Y,Q,q,W,J,$],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:contents}.dashboard[_ngcontent-%COMP%]{flex:1;padding:18px;color:var(--text-primary);background:var(--bg-canvas)}.stat-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}.stat-tile[_ngcontent-%COMP%]{text-align:left;padding:11px 13px;cursor:pointer;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);display:flex;flex-direction:column;gap:6px;color:var(--text-primary);font-family:inherit;transition:background .1s,border-color .1s}.stat-tile[_ngcontent-%COMP%]:hover{background:var(--bg-panel-2);border-color:var(--border-strong)}.stat-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.stat-value-row[_ngcontent-%COMP%]{justify-content:space-between;align-items:flex-end;gap:8px}.stat-value[_ngcontent-%COMP%]{font-size:23px;font-weight:650;letter-spacing:-.02em;line-height:1;min-height:23px}.center-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-bottom:14px}.graph-card[_ngcontent-%COMP%], .tips-card[_ngcontent-%COMP%]{height:340px;display:flex;flex-direction:column;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg);overflow:hidden}.card-head[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:11px 13px;border-bottom:1px solid var(--border-subtle);flex-shrink:0}.card-title[_ngcontent-%COMP%]{font-weight:600;font-size:12.5px;display:inline-flex;align-items:center;gap:8px}.mini-graph[_ngcontent-%COMP%]{flex:1;min-height:0;overflow:hidden;border-bottom-left-radius:var(--r-lg);border-bottom-right-radius:var(--r-lg)}.mini-graph[_ngcontent-%COMP%] app-graph-canvas[_ngcontent-%COMP%]{display:block;width:100%;height:100%}.seed-pill[_ngcontent-%COMP%]{color:var(--warn);background:var(--warn-soft);font-size:9.5px;font-weight:600;padding:1px 6px}.tips-body[_ngcontent-%COMP%]{flex:1;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:0}.tip-empty[_ngcontent-%COMP%]{color:var(--text-muted);font-size:12px;text-align:center;padding:12px}.tip-row[_ngcontent-%COMP%]{display:flex;gap:10px;padding:10px 12px;border-radius:8px;background:var(--bg-panel-2);border:1px solid var(--border-subtle);border-left-width:2.5px;animation:_ngcontent-%COMP%_slideInRight .2s ease;flex-shrink:0}.tip-sev-icon[_ngcontent-%COMP%]{flex-shrink:0;margin-top:1px}.tip-body-col[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:0}.tip-title[_ngcontent-%COMP%]{font-size:12.5px;font-weight:550;line-height:1.35;text-wrap:pretty}.tip-meta-row[_ngcontent-%COMP%]{margin-top:7px}.tip-fix[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-secondary);background:var(--bg-canvas);padding:2px 6px;border-radius:4px;border:1px solid var(--border-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}.heatmap-card[_ngcontent-%COMP%]{margin-bottom:14px}.heatmap-head[_ngcontent-%COMP%]{justify-content:space-between;margin-bottom:10px}.heatmap-legend[_ngcontent-%COMP%]{margin-top:9px;align-items:center}.heatmap-gradient[_ngcontent-%COMP%]{width:96px;height:6px;border-radius:999px;background:linear-gradient(90deg,var(--node-route),var(--warn),var(--error))}.bottom-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.4fr 1fr;gap:12px}.prompts-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:0}.prompts-head[_ngcontent-%COMP%]{justify-content:space-between;margin-bottom:6px}.prompt-row[_ngcontent-%COMP%]{display:flex;gap:10px;padding:7px 4px;border-radius:6px;cursor:pointer;align-items:center}.prompt-row[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.prompt-text[_ngcontent-%COMP%]{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prompt-right[_ngcontent-%COMP%]{text-align:right;flex-shrink:0}.prompt-cost[_ngcontent-%COMP%]{font-size:12px;font-weight:600}.prompt-cost.expensive[_ngcontent-%COMP%]{color:var(--error)}.cache-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.cache-headline[_ngcontent-%COMP%]{align-items:flex-end;gap:10px}.cache-rate[_ngcontent-%COMP%]{font-size:38px;font-weight:700;letter-spacing:-.03em;line-height:.9;color:var(--node-route)}.cache-divider[_ngcontent-%COMP%]{height:1px;background:var(--border-subtle)}.cache-kv-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:10px 14px}.kv[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:1px}.kv-label[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px}.kv-value[_ngcontent-%COMP%]{font-size:15px;font-weight:600}.kv-sub[_ngcontent-%COMP%]{font-size:9.5px}.dash-footer[_ngcontent-%COMP%]{margin-top:16px;text-align:right;font-size:10px}.dot-live[_ngcontent-%COMP%]{color:var(--success)}.dot-mock[_ngcontent-%COMP%]{color:var(--warn)}@keyframes _ngcontent-%COMP%_slideInRight{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}'],changeDetection:0})},Fe=[{id:"s-1",label:"validateSession",sub:"src/auth.ts",kind:"function",x:0,y:0},{id:"s-2",label:"checkExpiry",sub:"src/auth.ts",kind:"method",x:-180,y:-70},{id:"s-3",label:"signToken",sub:"src/auth.ts",kind:"function",x:-180,y:50},{id:"s-4",label:"AuthRoute",sub:"src/routes/auth.ts",kind:"route",x:200,y:-90},{id:"s-5",label:"login",sub:"src/routes/auth.ts",kind:"function",x:200,y:30},{id:"s-6",label:"logout",sub:"src/routes/auth.ts",kind:"function",x:230,y:110},{id:"s-7",label:"auth.test.ts",sub:"test/auth.test.ts",kind:"test",x:-240,y:140},{id:"s-8",label:"session.test.ts",sub:"test/session.test.ts",kind:"test",x:-100,y:180},{id:"s-9",label:"REQ-AUTH-005",sub:"reject expired tokens",kind:"spec",state:"drifted",x:30,y:-180},{id:"s-10",label:"REQ-AUTH-001",sub:"sign session tokens",kind:"spec",state:"verified",x:-150,y:-190},{id:"s-11",label:"User",sub:"src/types/user.ts",kind:"class",x:-340,y:-10},{id:"s-12",label:"Session",sub:"src/types/session.ts",kind:"class",x:60,y:130},{id:"s-13",label:"jwtSign",sub:"src/lib/jwt.ts",kind:"function",x:-340,y:80},{id:"s-14",label:"jwtVerify",sub:"src/lib/jwt.ts",kind:"function",x:350,y:-10},{id:"s-15",label:"tokenStore",sub:"src/db/tokens.ts",kind:"function",x:350,y:90}],$e=[{from:"s-1",to:"s-2",kind:"calls"},{from:"s-1",to:"s-3",kind:"calls"},{from:"s-4",to:"s-5",kind:"calls"},{from:"s-4",to:"s-6",kind:"calls"},{from:"s-5",to:"s-1",kind:"calls"},{from:"s-6",to:"s-1",kind:"calls"},{from:"s-3",to:"s-13",kind:"calls"},{from:"s-2",to:"s-14",kind:"calls"},{from:"s-1",to:"s-12",kind:"references"},{from:"s-5",to:"s-11",kind:"references"},{from:"s-9",to:"s-1",kind:"implements"},{from:"s-10",to:"s-3",kind:"implements"},{from:"s-7",to:"s-1",kind:"references"},{from:"s-8",to:"s-12",kind:"references"},{from:"s-14",to:"s-15",kind:"calls"}];function Ge(i){if(i.length===0)return[];let e=i[0],n=i.slice(1),t=[{id:e.id,label:e.label,sub:e.sub,kind:e.kind,x:0,y:0}],d=220;for(let h=0;h<n.length;h++){let k=h/n.length*Math.PI*2-Math.PI/2,x=n[h];t.push({id:x.id,label:x.label,sub:x.sub,kind:x.kind,x:Math.cos(k)*d,y:Math.sin(k)*d})}return t}export{X as Dashboard};