@selvakumaresra/specship 0.3.0 → 0.5.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 (97) hide show
  1. package/README.md +11 -1
  2. package/commands/ss-brainstorm.md +68 -0
  3. package/commands/ss-design-implement.md +5 -0
  4. package/commands/ss-design-loop.md +125 -0
  5. package/dist/analytics/specship-impact.d.ts +72 -0
  6. package/dist/analytics/specship-impact.d.ts.map +1 -0
  7. package/dist/analytics/specship-impact.js +216 -0
  8. package/dist/analytics/specship-impact.js.map +1 -0
  9. package/dist/bin/specship.js +70 -4
  10. package/dist/bin/specship.js.map +1 -1
  11. package/dist/db/migrations.d.ts +1 -1
  12. package/dist/db/migrations.d.ts.map +1 -1
  13. package/dist/db/migrations.js +15 -1
  14. package/dist/db/migrations.js.map +1 -1
  15. package/dist/db/schema.sql +8 -0
  16. package/dist/designer/artifact-store.js +54 -0
  17. package/dist/designer/browser.js +141 -0
  18. package/dist/designer/cdp-ensure.js +60 -0
  19. package/dist/designer/cdp-env.js +18 -0
  20. package/dist/designer/cdp-trace.js +599 -0
  21. package/dist/designer/cross-platform.js +74 -0
  22. package/dist/designer/designer-controller.js +1413 -0
  23. package/dist/designer/file-panel.js +39 -0
  24. package/dist/designer/interstitials.js +97 -0
  25. package/dist/designer/oopif-reader.js +176 -0
  26. package/dist/designer/package-meta.js +18 -0
  27. package/dist/designer/preview-host.js +50 -0
  28. package/dist/designer/repo-root.js +31 -0
  29. package/dist/designer/run-state.js +353 -0
  30. package/dist/designer/session-store.js +59 -0
  31. package/dist/designer/ui-anchors.js +651 -0
  32. package/dist/index.d.ts +27 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +48 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/installer/index.d.ts +7 -2
  37. package/dist/installer/index.d.ts.map +1 -1
  38. package/dist/installer/index.js +3 -2
  39. package/dist/installer/index.js.map +1 -1
  40. package/dist/installer/instructions-template.d.ts +17 -0
  41. package/dist/installer/instructions-template.d.ts.map +1 -1
  42. package/dist/installer/instructions-template.js +31 -1
  43. package/dist/installer/instructions-template.js.map +1 -1
  44. package/dist/installer/targets/claude.d.ts +19 -0
  45. package/dist/installer/targets/claude.d.ts.map +1 -1
  46. package/dist/installer/targets/claude.js +100 -1
  47. package/dist/installer/targets/claude.js.map +1 -1
  48. package/dist/installer/targets/shared.d.ts +14 -0
  49. package/dist/installer/targets/shared.d.ts.map +1 -1
  50. package/dist/installer/targets/shared.js +49 -0
  51. package/dist/installer/targets/shared.js.map +1 -1
  52. package/dist/installer/targets/types.d.ts +8 -0
  53. package/dist/installer/targets/types.d.ts.map +1 -1
  54. package/dist/mcp/designer-tools.d.ts +33 -0
  55. package/dist/mcp/designer-tools.d.ts.map +1 -0
  56. package/dist/mcp/designer-tools.js +313 -0
  57. package/dist/mcp/designer-tools.js.map +1 -0
  58. package/dist/mcp/tools.d.ts.map +1 -1
  59. package/dist/mcp/tools.js +22 -1
  60. package/dist/mcp/tools.js.map +1 -1
  61. package/dist/server/ingest/impact-backfill.js +69 -0
  62. package/dist/server/ingest/impact-query.js +343 -0
  63. package/dist/server/ingest/index.js +2 -1
  64. package/dist/server/ingest/ingestor.js +41 -6
  65. package/dist/server/ingest/specship-classify.js +153 -0
  66. package/dist/server/routes/claude.js +32 -0
  67. package/dist/server/routes/spec.js +94 -0
  68. package/dist/server/server.js +26 -2
  69. package/dist/web/{chunk-JN6W7HCN.js → chunk-45QHGCB4.js} +1 -1
  70. package/dist/web/{chunk-RAAMPHPJ.js → chunk-A5R3MJMO.js} +1 -1
  71. package/dist/web/{chunk-2DHIGIOI.js → chunk-ASZ77FMZ.js} +1 -1
  72. package/dist/web/chunk-D5OCNEJA.js +2 -0
  73. package/dist/web/{chunk-3SEJX2BK.js → chunk-FHZHD2ZG.js} +1 -1
  74. package/dist/web/chunk-GR72OOCN.js +1 -0
  75. package/dist/web/{chunk-YAWCRPHV.js → chunk-NZEZCT65.js} +1 -1
  76. package/dist/web/chunk-O7434ZMN.js +1 -0
  77. package/dist/web/chunk-ODX6CT3I.js +6 -0
  78. package/dist/web/chunk-RASJHUXS.js +1 -0
  79. package/dist/web/chunk-TQ3P2QZO.js +1 -0
  80. package/dist/web/{chunk-BCZM5AXU.js → chunk-UBOZGQNK.js} +1 -1
  81. package/dist/web/chunk-WCHGDXWC.js +1 -0
  82. package/dist/web/{chunk-BPECIDVO.js → chunk-WCKHQIYN.js} +1 -1
  83. package/dist/web/{chunk-JFYVCXK3.js → chunk-WLIMNDS3.js} +1 -1
  84. package/dist/web/{chunk-LV4G6QFG.js → chunk-YAMRN47K.js} +1 -1
  85. package/dist/web/index.html +1 -1
  86. package/dist/web/main-X2KCYXZ4.js +1 -0
  87. package/dist/web/sw.js +69 -0
  88. package/dist/workflows/defaults/claude-design-implement.yaml +138 -49
  89. package/hooks/hooks.json +11 -0
  90. package/package.json +7 -3
  91. package/selectors.json +41 -0
  92. package/dist/web/chunk-2OKMB4KX.js +0 -2
  93. package/dist/web/chunk-4N5DWG46.js +0 -1
  94. package/dist/web/chunk-DA6SNNAF.js +0 -1
  95. package/dist/web/chunk-JT7P3DEK.js +0 -6
  96. package/dist/web/chunk-TWXZK6XM.js +0 -1
  97. package/dist/web/main-WVI3YTDU.js +0 -1
@@ -25,6 +25,54 @@ function safeProjectPath(projectRoot, relPath) {
25
25
  return null;
26
26
  return abs;
27
27
  }
28
+ /**
29
+ * Extract the `brief:` value from the leading YAML frontmatter block of a
30
+ * spec source file (between the first pair of `---` fences). Returns null
31
+ * when there is no frontmatter, no `brief:` key, or the value is empty.
32
+ *
33
+ * Deliberately dependency-free: a simple line scan that mirrors the style
34
+ * used by `MarkdownSpecExtractor.parseFrontmatter`. Exported so tests can
35
+ * exercise the parsing logic in isolation.
36
+ */
37
+ export function parseBriefField(source) {
38
+ const lines = source.split(/\r?\n/);
39
+ if (lines.length === 0 || (lines[0] ?? '').trim() !== '---')
40
+ return null;
41
+ // Find the closing `---` fence.
42
+ let closingIdx = -1;
43
+ for (let i = 1; i < lines.length; i++) {
44
+ if ((lines[i] ?? '').trim() === '---') {
45
+ closingIdx = i;
46
+ break;
47
+ }
48
+ }
49
+ if (closingIdx === -1)
50
+ return null;
51
+ // Scan frontmatter body for `brief: <value>`.
52
+ for (let i = 1; i < closingIdx; i++) {
53
+ const line = (lines[i] ?? '').trim();
54
+ if (!line.startsWith('brief:'))
55
+ continue;
56
+ let value = line.slice('brief:'.length).trim();
57
+ if (!value)
58
+ return null;
59
+ // Strip surrounding quotes.
60
+ if ((value.startsWith('"') && value.endsWith('"')) ||
61
+ (value.startsWith("'") && value.endsWith("'"))) {
62
+ value = value.slice(1, -1).trim();
63
+ }
64
+ else {
65
+ // Strip a trailing ` # comment` from an UNQUOTED value only. Requires
66
+ // whitespace before the `#` so a `#fragment` inside the path — or a `#`
67
+ // inside a quoted value (handled above) — isn't mangled.
68
+ const hashIdx = value.search(/\s#/);
69
+ if (hashIdx !== -1)
70
+ value = value.slice(0, hashIdx).trim();
71
+ }
72
+ return value || null;
73
+ }
74
+ return null;
75
+ }
28
76
  /**
29
77
  * Atomic file write: tmp + rename. Mirrors `atomicWriteFileSync` in
30
78
  * `src/installer/targets/shared.ts` — kept local here to avoid the
@@ -83,6 +131,52 @@ export async function registerSpecRoutes(app) {
83
131
  }
84
132
  return { spec, parent, siblings, children, links, source };
85
133
  });
134
+ /**
135
+ * GET /api/spec/:id/brief — return the brainstorm brief for a spec.
136
+ *
137
+ * Reads the spec's source file, parses the `brief:` frontmatter key, and
138
+ * returns the brief markdown from the path it names. The `brief:` value is
139
+ * resolved relative to the spec file's own directory (so a nested spec at
140
+ * `specs/area/foo.md` with `brief: foo/brief.md` resolves to
141
+ * `specs/area/foo/brief.md`). safeProjectPath guards against traversal.
142
+ */
143
+ app.get('/api/spec/:id/brief', async (req, reply) => {
144
+ const cg = await resolveCg(app, req, reply);
145
+ if (!cg)
146
+ return;
147
+ const spec = cg.getSpecQueries().getSpecById(req.params.id);
148
+ if (!spec)
149
+ return reply.code(404).send({ error: 'spec not found' });
150
+ const projectRoot = cg.getProjectRoot();
151
+ const specAbs = safeProjectPath(projectRoot, spec.sourcePath);
152
+ if (!specAbs)
153
+ return reply.code(404).send({ error: 'no brief' });
154
+ // TOCTOU: read directly under try/catch rather than existsSync-then-read,
155
+ // so a file deleted between the check and the read degrades to 404 (the
156
+ // sibling GET /api/spec/:id read is guarded the same way) instead of 500.
157
+ let specSource;
158
+ try {
159
+ specSource = fs.readFileSync(specAbs, 'utf-8');
160
+ }
161
+ catch {
162
+ return reply.code(404).send({ error: 'no brief' });
163
+ }
164
+ const briefRel = parseBriefField(specSource);
165
+ if (!briefRel)
166
+ return reply.code(404).send({ error: 'no brief' });
167
+ // CONVENTION: `brief:` is relative to the SPEC FILE's own directory (resolves
168
+ // whether the spec is flat at specs/<id>.md or nested at specs/<area>/<id>.md).
169
+ // safeProjectPath GUARDS against traversal outside the project root.
170
+ const briefAbs = safeProjectPath(projectRoot, path.join(path.dirname(spec.sourcePath), briefRel));
171
+ if (!briefAbs)
172
+ return reply.code(404).send({ error: 'no brief' });
173
+ try {
174
+ return { path: briefRel, markdown: fs.readFileSync(briefAbs, 'utf-8') };
175
+ }
176
+ catch {
177
+ return reply.code(404).send({ error: 'no brief' });
178
+ }
179
+ });
86
180
  app.get('/api/drift', async (req, reply) => {
87
181
  const cg = await resolveCg(app, req, reply);
88
182
  if (!cg)
@@ -16,7 +16,8 @@ import { existsSync, promises as fs } from 'node:fs';
16
16
  import { fileURLToPath, pathToFileURL } from 'node:url';
17
17
  import Fastify from 'fastify';
18
18
  import cors from '@fastify/cors';
19
- import { startWatcher } from './ingest/index.js';
19
+ import { startWatcher, primaryProjectMatcher } from './ingest/index.js';
20
+ import { backfillDisplaced } from './ingest/impact-backfill.js';
20
21
  import { ProjectRegistry } from './project-registry.js';
21
22
  import { makeStaticHandler } from './static-handler.js';
22
23
  import { registerGraphRoutes } from './routes/graph.js';
@@ -101,10 +102,33 @@ export async function createServer(options) {
101
102
  const cgAny = primaryCg;
102
103
  const dbHandle = cgAny.db?.getDb ? cgAny.db.getDb() : cgAny.queries?.db;
103
104
  if (dbHandle) {
104
- watcher = startWatcher(dbHandle, { verbose });
105
+ // Build a sync resolveGraph: for the primary project path return the
106
+ // already-open SpecShip instance (which satisfies GraphLike).
107
+ // Sessions from other project paths resolve to null — they'll be left
108
+ // as 'unresolved' and retried on the next boot when that project is primary.
109
+ // The stored project_path is the lossy-decoded slug (every '-' → '/'), so
110
+ // an exact compare against the real primaryPath never matched and savings
111
+ // stayed 0. primaryProjectMatcher accepts both the real path and its
112
+ // mangled stored form. Sessions from OTHER projects still resolve to null
113
+ // (left 'unresolved', retried when that project is primary).
114
+ const primaryPath = options.projectRoot ?? null;
115
+ const isPrimary = primaryPath ? primaryProjectMatcher(primaryPath) : () => false;
116
+ const resolveGraph = (projectPath) => primaryPath && isPrimary(projectPath) ? primaryCg : null;
117
+ watcher = startWatcher(dbHandle, { verbose, resolveGraph });
105
118
  ownedWatcher = true;
106
119
  if (verbose)
107
120
  console.error('[specship-server] JSONL ingest watcher started');
121
+ // Backfill displaced_files / resolution for pre-upgrade rows (is_specship=1,
122
+ // resolution IS NULL). Idempotent — safe to run on every boot. Non-fatal:
123
+ // a failure here must never abort server startup.
124
+ try {
125
+ backfillDisplaced(dbHandle, resolveGraph);
126
+ if (verbose)
127
+ console.error('[specship-server] specship-impact backfill complete');
128
+ }
129
+ catch (err) {
130
+ console.error('[specship-server] specship-impact backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
131
+ }
108
132
  }
109
133
  }
110
134
  else if (!primaryCg && options.ingest !== false && verbose) {
@@ -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};
@@ -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};
@@ -1 +1 @@
1
- import{a as q}from"./chunk-EMGMOEVR.js";import{a as Q}from"./chunk-X2HTISHL.js";import{a as N}from"./chunk-UYC52MBC.js";import{a as R}from"./chunk-WDU3WICG.js";import{a as $,b as j}from"./chunk-HZA6NEAB.js";import{b as V}from"./chunk-4N5DWG46.js";import{c as M}from"./chunk-SHPTC4RL.js";import{a as L}from"./chunk-7RNS77UP.js";import{a as O}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-PDN6QYGJ.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
1
+ import{a as q}from"./chunk-EMGMOEVR.js";import{a as Q}from"./chunk-X2HTISHL.js";import{a as N}from"./chunk-UYC52MBC.js";import{a as R}from"./chunk-WDU3WICG.js";import{a as $,b as j}from"./chunk-HZA6NEAB.js";import{c as V}from"./chunk-GR72OOCN.js";import{c as M}from"./chunk-SHPTC4RL.js";import{a as L}from"./chunk-7RNS77UP.js";import{a as O}from"./chunk-E44X4RH2.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-PDN6QYGJ.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
@@ -0,0 +1 @@
1
+ import{a as j}from"./chunk-7RNS77UP.js";import{a as A,b as R}from"./chunk-E44X4RH2.js";import{E as u,I as i,R as b,W as o,X as v,lb as g}from"./chunk-PDN6QYGJ.js";import{a as y,b as m}from"./chunk-Q7L6LLAK.js";var w="specship.lastOnline",l=class r{onlineSig=o(!0);lastOnlineAtSig=o(null);online=this.onlineSig.asReadonly();lastOnlineAt=this.lastOnlineAtSig.asReadonly();lastOnlineLabel=g(()=>{let t=this.lastOnlineAtSig();if(t===null)return null;let e=Date.now()-t;return e<1e4?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:e<864e5?`${Math.round(e/36e5)}h ago`:`${Math.round(e/864e5)}d ago`});constructor(){if(typeof localStorage<"u")try{let t=localStorage.getItem(w),e=t?Number(t):NaN;Number.isFinite(e)&&this.lastOnlineAtSig.set(e)}catch{}typeof window<"u"&&window.addEventListener("offline",()=>this.onlineSig.set(!1))}noteSuccess(){let t=Date.now();if(this.lastOnlineAtSig.set(t),typeof localStorage<"u")try{localStorage.setItem(w,String(t))}catch{}this.onlineSig()||this.onlineSig.set(!0)}noteOffline(){this.onlineSig()&&this.onlineSig.set(!1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var f=class r{api=i(A);projects=i(j);connection=i(l);tickSig=o(0);loadingSig=o(!1);errorSig=o(null);lastRefreshSig=o(null);tick=this.tickSig.asReadonly();loading=this.loadingSig.asReadonly();error=this.errorSig.asReadonly();lastRefreshAt=this.lastRefreshSig.asReadonly();lastRefreshLabel=g(()=>{let t=this.lastRefreshSig();if(t===null)return null;let e=Date.now()-t;return e<5e3?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:`${Math.round(e/36e5)}h ago`});async triggerGlobalRefresh(){if(!this.loadingSig()){if(!this.connection.online()){this.errorSig.set("Offline \u2014 reconnect to refresh");return}this.loadingSig.set(!0),this.errorSig.set(null);try{let t=this.projects.projectQuery(),e=await this.api.post(`/api/refresh${t}`,{});(e.syncError||e.ingestError)&&this.errorSig.set([e.syncError,e.ingestError].filter(Boolean).join(" \xB7 ")),this.lastRefreshSig.set(Date.now()),this.tickSig.update(d=>d+1)}catch(t){this.errorSig.set(t instanceof Error?t.message:String(t))}finally{this.loadingSig.set(!1)}}}notifyLocalChange(){this.lastRefreshSig.set(Date.now()),this.tickSig.update(t=>t+1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var _="specship.cache:";function M(r){if(typeof localStorage>"u")return null;try{let t=localStorage.getItem(_+r);if(!t)return null;let e=JSON.parse(t);if(e&&typeof e.ts=="number"&&"data"in e)return e}catch{}return null}function O(r,t){let e=Date.now();if(typeof localStorage>"u")return e;try{localStorage.setItem(_+r,JSON.stringify({data:t,ts:e}))}catch{}return e}function K(r,t){let e=o({data:null,loading:!0,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null}),d=i(b),E=i(f),h=i(l),S=o(0),D=()=>{let a=t();if(!a){e.set({data:null,loading:!1,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null});return}s&&s.abort(),s=new AbortController,e.update(n=>m(y({},n),{loading:!0,error:null,noProject:!1})),r.get(a,s.signal).then(n=>{let c=O(a,n);h.noteSuccess(),e.set({data:n,loading:!1,error:null,source:"api",noProject:!1,stale:!1,cachedAt:c})}).catch(n=>{if(n instanceof Error&&n.name==="AbortError")return;if(n instanceof R){h.noteSuccess();let p=n.status===409&&(n.code==="no_project"||n.code==="no_primary");e.set({data:null,loading:!1,error:p?null:n,source:"api",noProject:p,stale:!1,cachedAt:null});return}h.noteOffline();let c=M(a);c?e.set({data:c.data,loading:!1,error:null,source:"api",noProject:!1,stale:!0,cachedAt:c.ts}):e.set({data:null,loading:!1,error:n instanceof Error?n:new Error(String(n)),source:"api",noProject:!1,stale:!0,cachedAt:null})})},s=null;return v(()=>{t(),S(),E.tick(),D()}),d.onDestroy(()=>{s?.abort()}),{state:e,refetch:()=>S.update(a=>a+1)}}export{l as a,f as b,K as c};
@@ -1 +1 @@
1
- import{a as D}from"./chunk-X2HTISHL.js";import{a as $}from"./chunk-UYC52MBC.js";import{a as R}from"./chunk-WDU3WICG.js";import{b as I}from"./chunk-4N5DWG46.js";import{c as F}from"./chunk-SHPTC4RL.js";import{a as O}from"./chunk-7RNS77UP.js";import{a as z}from"./chunk-E44X4RH2.js";import{Aa as c,Ga as h,I as k,Ia as m,Ka as p,M as f,N as u,Va as l,W,Wa as y,Xa as b,bb as _,ea as o,ka as P,lb as V,ra as w,sa as x,ua as M,va as v,wa as C,xa as s,ya as i,za as r,zb as j}from"./chunk-PDN6QYGJ.js";import{a as S,b as T}from"./chunk-Q7L6LLAK.js";var g=()=>[],A=(t,n)=>n.workflow.name,N=(t,n)=>n.name;function L(t,n){t&1&&c(0,"app-pick-project-empty",0)}function G(t,n){if(t&1&&(i(0,"code",15),l(1),r()),t&2){let e=n.$implicit;o(),y(e)}}function H(t,n){if(t&1&&(i(0,"code",17),l(1),r()),t&2){let e=n.$implicit;o(),b("$",e.name)}}function Q(t,n){if(t&1&&(i(0,"span",16),l(1,"inputs"),r(),v(2,H,2,1,"code",17,N)),t&2){let e=p().$implicit;o(2),C(e.workflow.inputs??_(0,g))}}function Y(t,n){if(t&1){let e=h();i(0,"div",4)(1,"div",6)(2,"span",7),l(3),r(),i(4,"app-pill",8),l(5),r(),c(6,"span",9),i(7,"button",10),m("click",function(){let d=f(e).$implicit,E=p(2);return u(E.openModal(d))}),c(8,"app-icon",11),l(9," Run "),r()(),i(10,"div",12),l(11),r(),i(12,"div",13)(13,"span",14),l(14,"requires"),r(),v(15,G,2,1,"code",15,M),w(17,Q,4,1),r()()}if(t&2){let e=n.$implicit,a=p(2);o(3),y(e.workflow.name),o(),s("color",a.scopeColor[e.scope])("bg",a.scopeBg[e.scope]),o(),y(e.scope),o(3),s("size",12),o(3),y(e.workflow.description||"\u2014"),o(4),C(e.workflow.requires??_(7,g)),o(2),x((e.workflow.inputs??_(8,g)).length>0?17:-1)}}function J(t,n){t&1&&(i(0,"span",33),l(1," *"),r())}function K(t,n){if(t&1){let e=h();i(0,"div",31)(1,"label",32),l(2),w(3,J,2,0,"span",33),r(),i(4,"input",34),m("input",function(d){let E=f(e).$implicit,B=p(4);return u(B.setVal(E.name,d.target.value))}),r()()}if(t&2){let e=n.$implicit,a=p(4);o(2),b(" ",e.name," "),o(),x(e.required?3:-1),o(),s("placeholder",e.description||e.name)("value",a.modalVals()[e.name]||"")}}function U(t,n){if(t&1&&v(0,K,5,4,"div",31,N),t&2){let e=p();C(e.workflow.inputs??_(0,g))}}function X(t,n){t&1&&(i(0,"div",27),l(1,"No inputs required."),r())}function Z(t,n){if(t&1&&(i(0,"app-pill"),c(1,"app-icon",35),l(2),r()),t&2){let e=n.$implicit;o(),s("size",10),o(),b(" ",e," ")}}function ee(t,n){if(t&1&&(i(0,"div",28),v(1,Z,3,2,"app-pill",null,M),r()),t&2){let e=p();o(),C(e.workflow.requires??_(0,g))}}function te(t,n){if(t&1){let e=h();i(0,"div",18),m("mousedown",function(){f(e);let d=p(2);return u(d.closeModal())}),i(1,"div",19),m("mousedown",function(d){return d.stopPropagation()}),i(2,"div",20),c(3,"app-icon",21),i(4,"span",22),l(5),r(),i(6,"button",23),m("click",function(){f(e);let d=p(2);return u(d.closeModal())}),c(7,"app-icon",24),r()(),i(8,"div",25)(9,"div",26),l(10),r(),w(11,U,2,1)(12,X,2,0,"div",27),w(13,ee,3,1,"div",28),r(),i(14,"div",29)(15,"button",30),m("click",function(){f(e);let d=p(2);return u(d.closeModal())}),l(16,"Cancel"),r(),i(17,"button",10),m("click",function(){f(e);let d=p(2);return u(d.launchRun())}),c(18,"app-icon",11),l(19," Launch run "),r()()()()}if(t&2){let e=n;o(3),s("size",16),o(2),y(e.workflow.name),o(2),s("size",14),o(3),b(" ",e.workflow.description," "),o(),x((e.workflow.inputs??_(7,g)).length>0?11:12),o(2),x((e.workflow.requires??_(8,g)).length>0?13:-1),o(5),s("size",13)}}function ne(t,n){if(t&1&&(i(0,"div",1),c(1,"app-page-head",2),i(2,"div",3),v(3,Y,18,9,"div",4,A),r()(),w(5,te,20,9,"div",5)),t&2){let e,a=p();o(3),C(a.entries()),o(2),x((e=a.modalEntry())?5:-1,e)}}var q=class t{api=k(z);projects=k(O);router=k(F);resource=I(this.api,()=>`/api/workflows${this.projects.projectQuery()}`);entries=V(()=>this.resource.state().data?.workflows??[]);modalEntry=W(null);modalVals=W({});scopeColor={bundled:"var(--node-spec)",global:"var(--node-code)",project:"var(--node-route)"};scopeBg={bundled:"color-mix(in srgb, var(--node-spec) 14%, transparent)",global:"color-mix(in srgb, var(--node-code) 14%, transparent)",project:"color-mix(in srgb, var(--node-route) 14%, transparent)"};openModal(n){this.modalVals.set({}),this.modalEntry.set(n)}closeModal(){this.modalEntry.set(null)}setVal(n,e){this.modalVals.update(a=>T(S({},a),{[n]:e}))}async launchRun(){this.modalEntry()&&(this.closeModal(),this.router.navigate(["/runs"]))}static \u0275fac=function(e){return new(e||t)};static \u0275cmp=P({type:t,selectors:[["app-workflows"]],decls:2,vars:1,consts:[["surface","Workflows"],[1,"scroll-y","wf-page"],["icon","workflow","title","Workflows","sub","Run a YAML-defined DAG of agent, shell and approval steps"],[1,"wf-grid"],[1,"card","card-pad","wf-card"],[1,"wf-overlay"],[1,"row","gap-8"],[1,"mono","wf-name"],[3,"color","bg"],[1,"grow"],["type","button",1,"btn","btn-primary","btn-sm",3,"click"],["name","play",3,"size"],[1,"secondary","wf-desc"],[1,"row","gap-6","wf-footer"],[1,"muted",2,"font-size","10.5px"],[1,"mono","wf-req-chip"],[1,"muted",2,"font-size","10.5px","margin-left","6px"],[1,"mono","wf-inp-chip"],[1,"wf-overlay",3,"mousedown"],[1,"wf-modal",3,"mousedown"],[1,"row","gap-10","wf-modal-head"],["name","workflow",2,"color","var(--accent)",3,"size"],[1,"mono","grow",2,"font-weight","600"],["type","button",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"wf-modal-body"],[1,"secondary",2,"font-size","12.5px","margin-bottom","16px","line-height","1.55"],[1,"muted",2,"font-size","12px","padding","8px 0"],[1,"row","gap-6",2,"margin-top","6px","margin-bottom","4px"],[1,"row","gap-8","wf-modal-foot"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],[2,"margin-bottom","12px"],[1,"eyebrow",2,"display","block","margin-bottom","5px"],[2,"color","var(--error)"],[1,"input","mono",2,"width","100%",3,"input","placeholder","value"],["name","check",3,"size"]],template:function(e,a){e&1&&w(0,L,1,0,"app-pick-project-empty",0)(1,ne,6,1),e&2&&x(a.resource.state().noProject?0:1)},dependencies:[R,$,D,j],styles:["[_nghost-%COMP%]{display:contents}.wf-page[_ngcontent-%COMP%]{flex:1;padding:18px}.wf-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:12px}.wf-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.wf-name[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600}.wf-desc[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.5;min-height:36px}.wf-footer[_ngcontent-%COMP%]{flex-wrap:wrap;border-top:1px solid var(--border-subtle);padding-top:10px}.wf-req-chip[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-secondary);background:var(--bg-canvas);padding:1px 6px;border-radius:4px;font-family:var(--font-mono)}.wf-inp-chip[_ngcontent-%COMP%]{font-size:10.5px;color:var(--node-spec);background:var(--node-spec-soft);padding:1px 6px;border-radius:4px;font-family:var(--font-mono)}.wf-overlay[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;z-index:90;display:grid;place-items:center}.wf-modal[_ngcontent-%COMP%]{width:460px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-pop)}.wf-modal-head[_ngcontent-%COMP%]{padding:14px 16px;border-bottom:1px solid var(--border-subtle)}.wf-modal-body[_ngcontent-%COMP%]{padding:16px}.wf-modal-foot[_ngcontent-%COMP%]{padding:12px 16px;border-top:1px solid var(--border-subtle);justify-content:flex-end}"],changeDetection:0})};export{q as Workflows};
1
+ import{a as D}from"./chunk-X2HTISHL.js";import{a as $}from"./chunk-UYC52MBC.js";import{a as R}from"./chunk-WDU3WICG.js";import{c as I}from"./chunk-GR72OOCN.js";import{c as F}from"./chunk-SHPTC4RL.js";import{a as O}from"./chunk-7RNS77UP.js";import{a as z}from"./chunk-E44X4RH2.js";import{Aa as c,Ga as h,I as k,Ia as m,Ka as p,M as f,N as u,Va as l,W,Wa as y,Xa as b,bb as _,ea as o,ka as P,lb as V,ra as w,sa as x,ua as M,va as v,wa as C,xa as s,ya as i,za as r,zb as j}from"./chunk-PDN6QYGJ.js";import{a as S,b as T}from"./chunk-Q7L6LLAK.js";var g=()=>[],A=(t,n)=>n.workflow.name,N=(t,n)=>n.name;function L(t,n){t&1&&c(0,"app-pick-project-empty",0)}function G(t,n){if(t&1&&(i(0,"code",15),l(1),r()),t&2){let e=n.$implicit;o(),y(e)}}function H(t,n){if(t&1&&(i(0,"code",17),l(1),r()),t&2){let e=n.$implicit;o(),b("$",e.name)}}function Q(t,n){if(t&1&&(i(0,"span",16),l(1,"inputs"),r(),v(2,H,2,1,"code",17,N)),t&2){let e=p().$implicit;o(2),C(e.workflow.inputs??_(0,g))}}function Y(t,n){if(t&1){let e=h();i(0,"div",4)(1,"div",6)(2,"span",7),l(3),r(),i(4,"app-pill",8),l(5),r(),c(6,"span",9),i(7,"button",10),m("click",function(){let d=f(e).$implicit,E=p(2);return u(E.openModal(d))}),c(8,"app-icon",11),l(9," Run "),r()(),i(10,"div",12),l(11),r(),i(12,"div",13)(13,"span",14),l(14,"requires"),r(),v(15,G,2,1,"code",15,M),w(17,Q,4,1),r()()}if(t&2){let e=n.$implicit,a=p(2);o(3),y(e.workflow.name),o(),s("color",a.scopeColor[e.scope])("bg",a.scopeBg[e.scope]),o(),y(e.scope),o(3),s("size",12),o(3),y(e.workflow.description||"\u2014"),o(4),C(e.workflow.requires??_(7,g)),o(2),x((e.workflow.inputs??_(8,g)).length>0?17:-1)}}function J(t,n){t&1&&(i(0,"span",33),l(1," *"),r())}function K(t,n){if(t&1){let e=h();i(0,"div",31)(1,"label",32),l(2),w(3,J,2,0,"span",33),r(),i(4,"input",34),m("input",function(d){let E=f(e).$implicit,B=p(4);return u(B.setVal(E.name,d.target.value))}),r()()}if(t&2){let e=n.$implicit,a=p(4);o(2),b(" ",e.name," "),o(),x(e.required?3:-1),o(),s("placeholder",e.description||e.name)("value",a.modalVals()[e.name]||"")}}function U(t,n){if(t&1&&v(0,K,5,4,"div",31,N),t&2){let e=p();C(e.workflow.inputs??_(0,g))}}function X(t,n){t&1&&(i(0,"div",27),l(1,"No inputs required."),r())}function Z(t,n){if(t&1&&(i(0,"app-pill"),c(1,"app-icon",35),l(2),r()),t&2){let e=n.$implicit;o(),s("size",10),o(),b(" ",e," ")}}function ee(t,n){if(t&1&&(i(0,"div",28),v(1,Z,3,2,"app-pill",null,M),r()),t&2){let e=p();o(),C(e.workflow.requires??_(0,g))}}function te(t,n){if(t&1){let e=h();i(0,"div",18),m("mousedown",function(){f(e);let d=p(2);return u(d.closeModal())}),i(1,"div",19),m("mousedown",function(d){return d.stopPropagation()}),i(2,"div",20),c(3,"app-icon",21),i(4,"span",22),l(5),r(),i(6,"button",23),m("click",function(){f(e);let d=p(2);return u(d.closeModal())}),c(7,"app-icon",24),r()(),i(8,"div",25)(9,"div",26),l(10),r(),w(11,U,2,1)(12,X,2,0,"div",27),w(13,ee,3,1,"div",28),r(),i(14,"div",29)(15,"button",30),m("click",function(){f(e);let d=p(2);return u(d.closeModal())}),l(16,"Cancel"),r(),i(17,"button",10),m("click",function(){f(e);let d=p(2);return u(d.launchRun())}),c(18,"app-icon",11),l(19," Launch run "),r()()()()}if(t&2){let e=n;o(3),s("size",16),o(2),y(e.workflow.name),o(2),s("size",14),o(3),b(" ",e.workflow.description," "),o(),x((e.workflow.inputs??_(7,g)).length>0?11:12),o(2),x((e.workflow.requires??_(8,g)).length>0?13:-1),o(5),s("size",13)}}function ne(t,n){if(t&1&&(i(0,"div",1),c(1,"app-page-head",2),i(2,"div",3),v(3,Y,18,9,"div",4,A),r()(),w(5,te,20,9,"div",5)),t&2){let e,a=p();o(3),C(a.entries()),o(2),x((e=a.modalEntry())?5:-1,e)}}var q=class t{api=k(z);projects=k(O);router=k(F);resource=I(this.api,()=>`/api/workflows${this.projects.projectQuery()}`);entries=V(()=>this.resource.state().data?.workflows??[]);modalEntry=W(null);modalVals=W({});scopeColor={bundled:"var(--node-spec)",global:"var(--node-code)",project:"var(--node-route)"};scopeBg={bundled:"color-mix(in srgb, var(--node-spec) 14%, transparent)",global:"color-mix(in srgb, var(--node-code) 14%, transparent)",project:"color-mix(in srgb, var(--node-route) 14%, transparent)"};openModal(n){this.modalVals.set({}),this.modalEntry.set(n)}closeModal(){this.modalEntry.set(null)}setVal(n,e){this.modalVals.update(a=>T(S({},a),{[n]:e}))}async launchRun(){this.modalEntry()&&(this.closeModal(),this.router.navigate(["/runs"]))}static \u0275fac=function(e){return new(e||t)};static \u0275cmp=P({type:t,selectors:[["app-workflows"]],decls:2,vars:1,consts:[["surface","Workflows"],[1,"scroll-y","wf-page"],["icon","workflow","title","Workflows","sub","Run a YAML-defined DAG of agent, shell and approval steps"],[1,"wf-grid"],[1,"card","card-pad","wf-card"],[1,"wf-overlay"],[1,"row","gap-8"],[1,"mono","wf-name"],[3,"color","bg"],[1,"grow"],["type","button",1,"btn","btn-primary","btn-sm",3,"click"],["name","play",3,"size"],[1,"secondary","wf-desc"],[1,"row","gap-6","wf-footer"],[1,"muted",2,"font-size","10.5px"],[1,"mono","wf-req-chip"],[1,"muted",2,"font-size","10.5px","margin-left","6px"],[1,"mono","wf-inp-chip"],[1,"wf-overlay",3,"mousedown"],[1,"wf-modal",3,"mousedown"],[1,"row","gap-10","wf-modal-head"],["name","workflow",2,"color","var(--accent)",3,"size"],[1,"mono","grow",2,"font-weight","600"],["type","button",1,"btn","btn-ghost","btn-xs",3,"click"],["name","x",3,"size"],[1,"wf-modal-body"],[1,"secondary",2,"font-size","12.5px","margin-bottom","16px","line-height","1.55"],[1,"muted",2,"font-size","12px","padding","8px 0"],[1,"row","gap-6",2,"margin-top","6px","margin-bottom","4px"],[1,"row","gap-8","wf-modal-foot"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],[2,"margin-bottom","12px"],[1,"eyebrow",2,"display","block","margin-bottom","5px"],[2,"color","var(--error)"],[1,"input","mono",2,"width","100%",3,"input","placeholder","value"],["name","check",3,"size"]],template:function(e,a){e&1&&w(0,L,1,0,"app-pick-project-empty",0)(1,ne,6,1),e&2&&x(a.resource.state().noProject?0:1)},dependencies:[R,$,D,j],styles:["[_nghost-%COMP%]{display:contents}.wf-page[_ngcontent-%COMP%]{flex:1;padding:18px}.wf-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:12px}.wf-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.wf-name[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600}.wf-desc[_ngcontent-%COMP%]{font-size:12.5px;line-height:1.5;min-height:36px}.wf-footer[_ngcontent-%COMP%]{flex-wrap:wrap;border-top:1px solid var(--border-subtle);padding-top:10px}.wf-req-chip[_ngcontent-%COMP%]{font-size:10.5px;color:var(--text-secondary);background:var(--bg-canvas);padding:1px 6px;border-radius:4px;font-family:var(--font-mono)}.wf-inp-chip[_ngcontent-%COMP%]{font-size:10.5px;color:var(--node-spec);background:var(--node-spec-soft);padding:1px 6px;border-radius:4px;font-family:var(--font-mono)}.wf-overlay[_ngcontent-%COMP%]{position:fixed;inset:0;background:#00000080;z-index:90;display:grid;place-items:center}.wf-modal[_ngcontent-%COMP%]{width:460px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-pop)}.wf-modal-head[_ngcontent-%COMP%]{padding:14px 16px;border-bottom:1px solid var(--border-subtle)}.wf-modal-body[_ngcontent-%COMP%]{padding:16px}.wf-modal-foot[_ngcontent-%COMP%]{padding:12px 16px;border-top:1px solid var(--border-subtle);justify-content:flex-end}"],changeDetection:0})};export{q as Workflows};
@@ -0,0 +1 @@
1
+ import{Ba as v,Ca as f,Da as y,Ja as D,Ka as M,O as d,ea as m,ka as u,lb as c,ob as b,pb as l,qa as h,ra as p,sa as g}from"./chunk-PDN6QYGJ.js";function L(i,e){if(i&1&&(d(),y(0,"path",1)(1,"path",2)),i&2){let t=M();h("d",t.fillD())("fill",t.color()),m(),h("d",t.pathD())("stroke",t.color())}}var C=class i{series=l([]);color=l("var(--accent)");height=l(200);hover=b();width=600;stats=c(()=>{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=c(()=>{let e=this.series();if(!e.length)return"";let t=this.width,n=this.height(),{max:r}=this.stats();return e.map((o,s)=>{let a=s/Math.max(1,e.length-1)*t,_=n-o.cost/r*(n-20)-10;return(s===0?"M":"L")+a.toFixed(2)+" "+_.toFixed(2)}).join(" ")});fillD=c(()=>{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(),r=(e.clientX-n.left)/n.width,o=this.series();if(!o.length)return;let s=Math.min(o.length-1,Math.max(0,Math.round(r*(o.length-1)))),a=o[s];a&&this.hover.emit(a)}static \u0275fac=function(t){return new(t||i)};static \u0275cmp=u({type:i,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&&(d(),v(0,"svg",0),D("mousemove",function(o){return n.onMove(o)})("mouseleave",function(){return n.onLeave()}),p(1,L,2,4),f()),t&2&&(h("viewBox","0 0 "+n.width+" "+n.height())("height",n.height()),m(),g(n.pathD()?1:-1))},styles:["[_nghost-%COMP%]{display:block}.line-chart[_ngcontent-%COMP%]{cursor:crosshair}"],changeDetection:0})};export{C as a};