@pennyfarthing/cyclist 10.4.0 → 11.0.0-alpha.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 (270) hide show
  1. package/dist/api/agent-load.d.ts +1 -2
  2. package/dist/api/agent-load.d.ts.map +1 -1
  3. package/dist/api/agent-load.js +2 -123
  4. package/dist/api/agent-load.js.map +1 -1
  5. package/dist/api/audit-log.d.ts +1 -17
  6. package/dist/api/audit-log.d.ts.map +1 -1
  7. package/dist/api/audit-log.js +2 -162
  8. package/dist/api/audit-log.js.map +1 -1
  9. package/dist/api/background-tasks.d.ts +1 -26
  10. package/dist/api/background-tasks.d.ts.map +1 -1
  11. package/dist/api/background-tasks.js +2 -55
  12. package/dist/api/background-tasks.js.map +1 -1
  13. package/dist/api/bell.d.ts +1 -18
  14. package/dist/api/bell.d.ts.map +1 -1
  15. package/dist/api/bell.js +2 -33
  16. package/dist/api/bell.js.map +1 -1
  17. package/dist/api/code-markers.d.ts +1 -8
  18. package/dist/api/code-markers.d.ts.map +1 -1
  19. package/dist/api/code-markers.js +2 -61
  20. package/dist/api/code-markers.js.map +1 -1
  21. package/dist/api/complexity.d.ts +1 -2
  22. package/dist/api/complexity.d.ts.map +1 -1
  23. package/dist/api/complexity.js +2 -46
  24. package/dist/api/complexity.js.map +1 -1
  25. package/dist/api/context.d.ts +1 -37
  26. package/dist/api/context.d.ts.map +1 -1
  27. package/dist/api/context.js +2 -143
  28. package/dist/api/context.js.map +1 -1
  29. package/dist/api/dead-code.d.ts +1 -2
  30. package/dist/api/dead-code.d.ts.map +1 -1
  31. package/dist/api/dead-code.js +2 -69
  32. package/dist/api/dead-code.js.map +1 -1
  33. package/dist/api/dependencies.d.ts +1 -2
  34. package/dist/api/dependencies.d.ts.map +1 -1
  35. package/dist/api/dependencies.js +2 -42
  36. package/dist/api/dependencies.js.map +1 -1
  37. package/dist/api/evaluation.d.ts +1 -19
  38. package/dist/api/evaluation.d.ts.map +1 -1
  39. package/dist/api/evaluation.js +2 -127
  40. package/dist/api/evaluation.js.map +1 -1
  41. package/dist/api/file-browser.d.ts +1 -8
  42. package/dist/api/file-browser.d.ts.map +1 -1
  43. package/dist/api/file-browser.js +2 -114
  44. package/dist/api/file-browser.js.map +1 -1
  45. package/dist/api/git.d.ts +1 -46
  46. package/dist/api/git.d.ts.map +1 -1
  47. package/dist/api/git.js +2 -354
  48. package/dist/api/git.js.map +1 -1
  49. package/dist/api/health-score.d.ts +1 -2
  50. package/dist/api/health-score.d.ts.map +1 -1
  51. package/dist/api/health-score.js +2 -46
  52. package/dist/api/health-score.js.map +1 -1
  53. package/dist/api/hook-request.d.ts +1 -40
  54. package/dist/api/hook-request.d.ts.map +1 -1
  55. package/dist/api/hook-request.js +2 -277
  56. package/dist/api/hook-request.js.map +1 -1
  57. package/dist/api/hotspots.d.ts +1 -2
  58. package/dist/api/hotspots.d.ts.map +1 -1
  59. package/dist/api/hotspots.js +2 -61
  60. package/dist/api/hotspots.js.map +1 -1
  61. package/dist/api/identity.d.ts +1 -16
  62. package/dist/api/identity.d.ts.map +1 -1
  63. package/dist/api/identity.js +2 -78
  64. package/dist/api/identity.js.map +1 -1
  65. package/dist/api/index.d.ts +1 -34
  66. package/dist/api/index.d.ts.map +1 -1
  67. package/dist/api/index.js +2 -44
  68. package/dist/api/index.js.map +1 -1
  69. package/dist/api/mode.d.ts +1 -22
  70. package/dist/api/mode.d.ts.map +1 -1
  71. package/dist/api/mode.js +2 -37
  72. package/dist/api/mode.js.map +1 -1
  73. package/dist/api/otlp.d.ts +1 -2
  74. package/dist/api/otlp.d.ts.map +1 -1
  75. package/dist/api/otlp.js +2 -46
  76. package/dist/api/otlp.js.map +1 -1
  77. package/dist/api/permissions.d.ts +1 -15
  78. package/dist/api/permissions.d.ts.map +1 -1
  79. package/dist/api/permissions.js +2 -66
  80. package/dist/api/permissions.js.map +1 -1
  81. package/dist/api/persona.d.ts +1 -8
  82. package/dist/api/persona.d.ts.map +1 -1
  83. package/dist/api/persona.js +2 -67
  84. package/dist/api/persona.js.map +1 -1
  85. package/dist/api/portrait.d.ts +1 -5
  86. package/dist/api/portrait.d.ts.map +1 -1
  87. package/dist/api/portrait.js +2 -27
  88. package/dist/api/portrait.js.map +1 -1
  89. package/dist/api/settings.d.ts +1 -53
  90. package/dist/api/settings.d.ts.map +1 -1
  91. package/dist/api/settings.js +2 -464
  92. package/dist/api/settings.js.map +1 -1
  93. package/dist/api/spans.d.ts +1 -16
  94. package/dist/api/spans.d.ts.map +1 -1
  95. package/dist/api/spans.js +2 -244
  96. package/dist/api/spans.js.map +1 -1
  97. package/dist/api/stats.d.ts +1 -12
  98. package/dist/api/stats.d.ts.map +1 -1
  99. package/dist/api/stats.js +2 -84
  100. package/dist/api/stats.js.map +1 -1
  101. package/dist/api/story.d.ts +1 -2
  102. package/dist/api/story.d.ts.map +1 -1
  103. package/dist/api/story.js +2 -14
  104. package/dist/api/story.js.map +1 -1
  105. package/dist/api/telemetry.d.ts +1 -18
  106. package/dist/api/telemetry.d.ts.map +1 -1
  107. package/dist/api/telemetry.js +2 -164
  108. package/dist/api/telemetry.js.map +1 -1
  109. package/dist/api/theme-agents.d.ts +1 -60
  110. package/dist/api/theme-agents.d.ts.map +1 -1
  111. package/dist/api/theme-agents.js +2 -213
  112. package/dist/api/theme-agents.js.map +1 -1
  113. package/dist/api/todos.d.ts +1 -32
  114. package/dist/api/todos.d.ts.map +1 -1
  115. package/dist/api/todos.js +2 -43
  116. package/dist/api/todos.js.map +1 -1
  117. package/dist/api/token-stats.d.ts +1 -7
  118. package/dist/api/token-stats.d.ts.map +1 -1
  119. package/dist/api/token-stats.js +2 -35
  120. package/dist/api/token-stats.js.map +1 -1
  121. package/dist/api/welcome.d.ts +1 -21
  122. package/dist/api/welcome.d.ts.map +1 -1
  123. package/dist/api/welcome.js +2 -34
  124. package/dist/api/welcome.js.map +1 -1
  125. package/dist/env.d.ts +6 -0
  126. package/dist/env.d.ts.map +1 -0
  127. package/dist/env.js +10 -0
  128. package/dist/env.js.map +1 -0
  129. package/dist/focus.d.ts +53 -0
  130. package/dist/focus.d.ts.map +1 -0
  131. package/dist/focus.js +122 -0
  132. package/dist/focus.js.map +1 -0
  133. package/dist/menu-builder.d.ts.map +1 -1
  134. package/dist/menu-builder.js +0 -1
  135. package/dist/menu-builder.js.map +1 -1
  136. package/dist/public/css/react.css +1 -1
  137. package/dist/public/js/react/react.js +51 -59
  138. package/dist/server.d.ts +16 -85
  139. package/dist/server.d.ts.map +1 -1
  140. package/dist/server.js +38 -409
  141. package/dist/server.js.map +1 -1
  142. package/dist/sprint-data.d.ts +1 -1
  143. package/dist/sprint-data.d.ts.map +1 -1
  144. package/dist/sprint-data.js +2 -2
  145. package/dist/sprint-data.js.map +1 -1
  146. package/dist/websocket.d.ts +2 -0
  147. package/dist/websocket.d.ts.map +1 -1
  148. package/dist/websocket.js +42 -75
  149. package/dist/websocket.js.map +1 -1
  150. package/package.json +3 -6
  151. package/portraits/hogans-heroes/large/burkhalter-35312.png +0 -0
  152. package/portraits/hogans-heroes/large/carter-34352.png +0 -0
  153. package/portraits/hogans-heroes/large/hochstetter-45314.png +0 -0
  154. package/portraits/hogans-heroes/large/hogan-44541.png +0 -0
  155. package/portraits/hogans-heroes/large/kinch-35241.png +0 -0
  156. package/portraits/hogans-heroes/large/klink-23434.png +0 -0
  157. package/portraits/hogans-heroes/large/lebeau-45443.png +0 -0
  158. package/portraits/hogans-heroes/large/marya-53543.png +0 -0
  159. package/portraits/hogans-heroes/large/newkirk-54432.png +0 -0
  160. package/portraits/hogans-heroes/large/schultz-42453.png +0 -0
  161. package/portraits/hogans-heroes/large/underground-55131.png +0 -0
  162. package/portraits/hogans-heroes/medium/burkhalter-35312.png +0 -0
  163. package/portraits/hogans-heroes/medium/carter-34352.png +0 -0
  164. package/portraits/hogans-heroes/medium/hochstetter-45314.png +0 -0
  165. package/portraits/hogans-heroes/medium/hogan-44541.png +0 -0
  166. package/portraits/hogans-heroes/medium/kinch-35241.png +0 -0
  167. package/portraits/hogans-heroes/medium/klink-23434.png +0 -0
  168. package/portraits/hogans-heroes/medium/lebeau-45443.png +0 -0
  169. package/portraits/hogans-heroes/medium/marya-53543.png +0 -0
  170. package/portraits/hogans-heroes/medium/newkirk-54432.png +0 -0
  171. package/portraits/hogans-heroes/medium/schultz-42453.png +0 -0
  172. package/portraits/hogans-heroes/medium/underground-55131.png +0 -0
  173. package/portraits/monty-python/large/announcer-44441.png +0 -0
  174. package/portraits/monty-python/large/arguer-35412.png +0 -0
  175. package/portraits/monty-python/large/bicycle-repair-man-35241.png +0 -0
  176. package/portraits/monty-python/large/colonel-35423.png +0 -0
  177. package/portraits/monty-python/large/counsellor-45341.png +0 -0
  178. package/portraits/monty-python/large/gumbys-23524.png +0 -0
  179. package/portraits/monty-python/large/nudge-43533.png +0 -0
  180. package/portraits/monty-python/large/praline-45413.png +0 -0
  181. package/portraits/monty-python/large/silly-walks-55322.png +0 -0
  182. package/portraits/monty-python/large/wensleydale-54451.png +0 -0
  183. package/portraits/monty-python/large/xim-nez-43534.png +0 -0
  184. package/portraits/monty-python/medium/announcer-44441.png +0 -0
  185. package/portraits/monty-python/medium/arguer-35412.png +0 -0
  186. package/portraits/monty-python/medium/bicycle-repair-man-35241.png +0 -0
  187. package/portraits/monty-python/medium/colonel-35423.png +0 -0
  188. package/portraits/monty-python/medium/counsellor-45341.png +0 -0
  189. package/portraits/monty-python/medium/gumbys-23524.png +0 -0
  190. package/portraits/monty-python/medium/nudge-43533.png +0 -0
  191. package/portraits/monty-python/medium/praline-45413.png +0 -0
  192. package/portraits/monty-python/medium/silly-walks-55322.png +0 -0
  193. package/portraits/monty-python/medium/wensleydale-54451.png +0 -0
  194. package/portraits/monty-python/medium/xim-nez-43534.png +0 -0
  195. package/portraits/stephen-king/large/andy-55231.png +0 -0
  196. package/portraits/stephen-king/large/christine-25112.png +0 -0
  197. package/portraits/stephen-king/large/danny-53243.png +0 -0
  198. package/portraits/stephen-king/large/flagg-55311.png +0 -0
  199. package/portraits/stephen-king/large/gaunt-54421.png +0 -0
  200. package/portraits/stephen-king/large/jack-44224.png +0 -0
  201. package/portraits/stephen-king/large/johnny-44353.png +0 -0
  202. package/portraits/stephen-king/large/margaret-15415.png +0 -0
  203. package/portraits/stephen-king/large/paul-45233.png +0 -0
  204. package/portraits/stephen-king/large/pennywise-54411.png +0 -0
  205. package/portraits/stephen-king/large/roland-35121.png +0 -0
  206. package/portraits/stephen-king/medium/andy-55231.png +0 -0
  207. package/portraits/stephen-king/medium/christine-25112.png +0 -0
  208. package/portraits/stephen-king/medium/danny-53243.png +0 -0
  209. package/portraits/stephen-king/medium/flagg-55311.png +0 -0
  210. package/portraits/stephen-king/medium/gaunt-54421.png +0 -0
  211. package/portraits/stephen-king/medium/jack-44224.png +0 -0
  212. package/portraits/stephen-king/medium/johnny-44353.png +0 -0
  213. package/portraits/stephen-king/medium/margaret-15415.png +0 -0
  214. package/portraits/stephen-king/medium/paul-45233.png +0 -0
  215. package/portraits/stephen-king/medium/pennywise-54411.png +0 -0
  216. package/portraits/stephen-king/medium/roland-35121.png +0 -0
  217. package/src/public/App.tsx +21 -5
  218. package/src/public/components/BikeRackIndex.tsx +0 -1
  219. package/src/public/components/BikeRackWorkspace.tsx +86 -11
  220. package/src/public/components/DockviewWorkspace.tsx +19 -8
  221. package/src/public/components/StandalonePanel.tsx +1 -3
  222. package/src/public/components/panel-registry.ts +3 -1
  223. package/src/public/components/panels/AuditLogPanel.tsx +28 -4
  224. package/src/public/components/panels/GitPanel.tsx +1 -20
  225. package/src/public/components/panels/SettingsPanel.tsx +0 -1
  226. package/src/public/components/panels/SprintPanel.tsx +32 -1
  227. package/src/public/components/panels/index.ts +0 -2
  228. package/src/public/hooks/useFocusPanel.ts +137 -0
  229. package/src/public/hooks/useLayoutPersistence.ts +8 -5
  230. package/src/public/styles/dockview-theme.css +1 -84
  231. package/src/public/styles/tailwind.css +27 -32
  232. package/src/public/utils/slash-commands.ts +122 -98
  233. package/dist/hooks/cyclist-pretooluse-hook.d.ts +0 -60
  234. package/dist/hooks/cyclist-pretooluse-hook.d.ts.map +0 -1
  235. package/dist/hooks/cyclist-pretooluse-hook.js +0 -57
  236. package/dist/hooks/cyclist-pretooluse-hook.js.map +0 -1
  237. package/dist/hooks/pretooluse-hook.d.ts +0 -89
  238. package/dist/hooks/pretooluse-hook.d.ts.map +0 -1
  239. package/dist/hooks/pretooluse-hook.js +0 -235
  240. package/dist/hooks/pretooluse-hook.js.map +0 -1
  241. package/dist/notification-sound.d.ts +0 -59
  242. package/dist/notification-sound.d.ts.map +0 -1
  243. package/dist/notification-sound.js +0 -219
  244. package/dist/notification-sound.js.map +0 -1
  245. package/dist/plugin-loader.test.d.ts +0 -17
  246. package/dist/plugin-loader.test.d.ts.map +0 -1
  247. package/dist/plugin-loader.test.js +0 -407
  248. package/dist/plugin-loader.test.js.map +0 -1
  249. package/portraits/star-trek-tng/large/beverly-44352.png +0 -0
  250. package/portraits/star-trek-tng/large/data-55241.png +0 -0
  251. package/portraits/star-trek-tng/large/deanna-43353.png +0 -0
  252. package/portraits/star-trek-tng/large/geordi-54342.png +0 -0
  253. package/portraits/star-trek-tng/large/jean-luc-45342.png +0 -0
  254. package/portraits/star-trek-tng/large/kathryn-45332.png +0 -0
  255. package/portraits/star-trek-tng/large/miles-35342.png +0 -0
  256. package/portraits/star-trek-tng/large/q-53521.png +0 -0
  257. package/portraits/star-trek-tng/large/spock-45231.png +0 -0
  258. package/portraits/star-trek-tng/large/troi-44352.png +0 -0
  259. package/portraits/star-trek-tng/medium/beverly-44352.png +0 -0
  260. package/portraits/star-trek-tng/medium/data-55241.png +0 -0
  261. package/portraits/star-trek-tng/medium/deanna-43353.png +0 -0
  262. package/portraits/star-trek-tng/medium/geordi-54342.png +0 -0
  263. package/portraits/star-trek-tng/medium/jean-luc-45342.png +0 -0
  264. package/portraits/star-trek-tng/medium/kathryn-45332.png +0 -0
  265. package/portraits/star-trek-tng/medium/miles-35342.png +0 -0
  266. package/portraits/star-trek-tng/medium/q-53521.png +0 -0
  267. package/portraits/star-trek-tng/medium/spock-45231.png +0 -0
  268. package/portraits/star-trek-tng/medium/troi-44352.png +0 -0
  269. package/src/public/components/panels/TTYPanel.tsx +0 -299
  270. package/src/public/types/electron.d.ts +0 -18
@@ -1,115 +1,3 @@
1
- /**
2
- * File Browser API Router
3
- *
4
- * REST endpoints for file browser functionality in web mode.
5
- * Mirrors the IPC handlers from main.ts for browser compatibility.
6
- */
7
- import { Router } from 'express';
8
- import { spawn } from 'child_process';
9
- import { existsSync } from 'fs';
10
- import { resolve, isAbsolute } from 'path';
11
- import { listDirectory, readFile } from '../file-browser.js';
12
- export function createFileBrowserRouter(getProjectDir) {
13
- const router = Router();
14
- // List directory contents
15
- router.get('/', (req, res) => {
16
- try {
17
- const projectDir = getProjectDir();
18
- const requestedPath = req.query.path || '';
19
- const listing = listDirectory(requestedPath, projectDir);
20
- res.json(listing);
21
- }
22
- catch (err) {
23
- console.error('[FileBrowser API] Error listing directory:', err);
24
- res.status(400).json({
25
- error: err instanceof Error ? err.message : 'Failed to list directory'
26
- });
27
- }
28
- });
29
- // Open/read a file
30
- router.post('/open', (req, res) => {
31
- try {
32
- const projectDir = getProjectDir();
33
- const { path: filePath } = req.body;
34
- if (!filePath) {
35
- return res.status(400).json({ error: 'Missing path parameter' });
36
- }
37
- const content = readFile(filePath, projectDir);
38
- res.json({ path: filePath, content });
39
- }
40
- catch (err) {
41
- console.error('[FileBrowser API] Error reading file:', err);
42
- res.status(400).json({
43
- error: err instanceof Error ? err.message : 'Failed to read file'
44
- });
45
- }
46
- });
47
- // Open file in GUI editor
48
- // Story MSSCI-12467: DIFFS panel file opener
49
- // Preference: Windsurf → VS Code → Notepad (ignores $EDITOR which may be terminal-based)
50
- router.post('/edit', async (req, res) => {
51
- try {
52
- const projectDir = getProjectDir();
53
- const { path: filePath, lineNumber } = req.body;
54
- if (!filePath) {
55
- return res.status(400).json({ success: false, error: 'Missing path parameter' });
56
- }
57
- // Resolve path (absolute or relative to project)
58
- const absolutePath = isAbsolute(filePath) ? filePath : resolve(projectDir, filePath);
59
- // Verify file exists
60
- if (!existsSync(absolutePath)) {
61
- return res.status(404).json({ success: false, error: 'File not found' });
62
- }
63
- // GUI editor preference order (ignores $EDITOR which may be vim/nano)
64
- const editorCandidates = ['windsurf', 'code', 'notepad'];
65
- // Find first available editor
66
- let editor = null;
67
- for (const candidate of editorCandidates) {
68
- try {
69
- const { execSync } = await import('child_process');
70
- // Check if command exists (works on macOS/Linux with 'which', Windows with 'where')
71
- const whichCmd = process.platform === 'win32' ? 'where' : 'which';
72
- execSync(`${whichCmd} ${candidate}`, { stdio: 'ignore' });
73
- editor = candidate;
74
- break;
75
- }
76
- catch {
77
- // Command not found, try next
78
- }
79
- }
80
- if (!editor) {
81
- return res.status(500).json({
82
- success: false,
83
- error: 'No GUI editor found. Install Windsurf, VS Code, or Notepad.'
84
- });
85
- }
86
- // Build command arguments (all these editors use similar syntax)
87
- let args;
88
- if (editor === 'windsurf' || editor === 'code') {
89
- // Windsurf / VS Code: --goto file:line
90
- args = lineNumber ? ['--goto', `${absolutePath}:${lineNumber}`] : [absolutePath];
91
- }
92
- else {
93
- // Notepad: just the file path
94
- args = [absolutePath];
95
- }
96
- console.log(`[FileBrowser API] Opening in editor: ${editor} ${args.join(' ')}`);
97
- // Spawn editor detached so it doesn't block the server
98
- const child = spawn(editor, args, {
99
- detached: true,
100
- stdio: 'ignore',
101
- });
102
- child.unref();
103
- res.json({ success: true, editor, path: absolutePath });
104
- }
105
- catch (err) {
106
- console.error('[FileBrowser API] Error opening editor:', err);
107
- res.status(500).json({
108
- success: false,
109
- error: err instanceof Error ? err.message : 'Failed to open editor'
110
- });
111
- }
112
- });
113
- return router;
114
- }
1
+ // Re-export from @pennyfarthing/core (Story 98-17)
2
+ export * from '@pennyfarthing/core/dist/server/api/file-browser.js';
115
3
  //# sourceMappingURL=file-browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-browser.js","sourceRoot":"","sources":["../../src/api/file-browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-browser.js","sourceRoot":"","sources":["../../src/api/file-browser.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,cAAc,qDAAqD,CAAC"}
package/dist/api/git.d.ts CHANGED
@@ -1,47 +1,2 @@
1
- import { Router } from 'express';
2
- export interface DirtyFile {
3
- status: string;
4
- path: string;
5
- }
6
- export interface GitInfo {
7
- branch: string;
8
- clean: boolean;
9
- ahead: number | null;
10
- behind: number | null;
11
- dirtyFiles: DirtyFile[];
12
- /** Commits that origin/develop has that local branch doesn't (needs pull/rebase) */
13
- developBehind: number | null;
14
- }
15
- export interface RepoGitInfo extends GitInfo {
16
- name: string;
17
- path: string;
18
- }
19
- interface RepoConfig {
20
- name: string;
21
- path: string;
22
- }
23
- /**
24
- * Get repos from repos.yaml
25
- * Checks project root first, then .claude/project/ fallback.
26
- * Returns array of repo configs, falls back to single repo (current dir) if none configured.
27
- */
28
- export declare function getReposFromConfig(projectDir: string): RepoConfig[];
29
- /**
30
- * Get git status for all configured repos (sync - blocks event loop, use getAllReposGitInfoAsync when possible)
31
- */
32
- export declare function getAllReposGitInfo(projectDir: string): RepoGitInfo[];
33
- /**
34
- * Get git status for all configured repos (async - does not block event loop)
35
- */
36
- export declare function getAllReposGitInfoAsync(projectDir: string): Promise<RepoGitInfo[]>;
37
- export declare function getGitInfo(projectDir: string): GitInfo | null;
38
- /**
39
- * Get git status for project (async - does not block event loop)
40
- * This should be preferred over getGitInfo for WebSocket broadcasts and polling
41
- * Uses a per-repo mutex to prevent git lock conflicts from concurrent operations
42
- */
43
- export declare function getGitInfoAsync(projectDir: string): Promise<GitInfo | null>;
44
- export declare function setForceRefreshCallback(callback: (projectDir: string) => Promise<void>): void;
45
- export declare function createGitRouter(getProjectDir: () => string): Router;
46
- export {};
1
+ export * from '@pennyfarthing/core/dist/server/api/git.js';
47
2
  //# sourceMappingURL=git.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/api/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA8CjC,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,oFAAoF;IACpF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAGD,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,EAAE,CAqCnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,EAAE,CAkBpE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxF;AAGD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAsF7D;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAqGjF;AAKD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAE7F;AAGD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,MAAM,GAAG,MAAM,CAqDnE"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/api/git.ts"],"names":[],"mappings":"AACA,cAAc,4CAA4C,CAAC"}
package/dist/api/git.js CHANGED
@@ -1,355 +1,3 @@
1
- import { Router } from 'express';
2
- import { exec, execSync } from 'child_process';
3
- import { promisify } from 'util';
4
- import { existsSync, readFileSync } from 'fs';
5
- import { join } from 'path';
6
- import { parse as parseYaml } from 'yaml';
7
- import { detectPennyfarthingProject } from '../pennyfarthing.js';
8
- const execAsync = promisify(exec);
9
- /**
10
- * Per-repo mutex to prevent concurrent git operations that cause lock conflicts
11
- * Maps repo path to a promise that resolves when the current operation completes
12
- */
13
- const repoLocks = new Map();
14
- /**
15
- * Acquire a lock for a repo, ensuring only one git operation runs at a time
16
- * Returns a release function to call when done
17
- */
18
- async function acquireRepoLock(repoPath) {
19
- // Wait for any existing operation to complete
20
- const existingLock = repoLocks.get(repoPath);
21
- if (existingLock) {
22
- await existingLock;
23
- }
24
- // Create a new lock
25
- let releaseLock;
26
- const lockPromise = new Promise(resolve => {
27
- releaseLock = resolve;
28
- });
29
- repoLocks.set(repoPath, lockPromise);
30
- return () => {
31
- releaseLock();
32
- // Clean up the lock after a short delay to allow batched requests
33
- setTimeout(() => {
34
- if (repoLocks.get(repoPath) === lockPromise) {
35
- repoLocks.delete(repoPath);
36
- }
37
- }, 100);
38
- };
39
- }
40
- /**
41
- * Get repos from repos.yaml
42
- * Checks project root first, then .claude/project/ fallback.
43
- * Returns array of repo configs, falls back to single repo (current dir) if none configured.
44
- */
45
- export function getReposFromConfig(projectDir) {
46
- // Check .pennyfarthing/ first (canonical runtime location), then project root fallback
47
- const candidates = [
48
- join(projectDir, '.pennyfarthing', 'repos.yaml'),
49
- join(projectDir, 'repos.yaml'),
50
- ];
51
- const configPath = candidates.find(p => existsSync(p));
52
- if (!configPath) {
53
- const dirName = projectDir.split('/').pop() || 'project';
54
- return [{ name: dirName, path: '.' }];
55
- }
56
- try {
57
- const configContent = readFileSync(configPath, 'utf-8');
58
- const config = parseYaml(configContent);
59
- if (!config?.repos || typeof config.repos !== 'object') {
60
- const dirName = projectDir.split('/').pop() || 'project';
61
- return [{ name: dirName, path: '.' }];
62
- }
63
- const repos = [];
64
- for (const [name, repoConfig] of Object.entries(config.repos)) {
65
- const rc = repoConfig;
66
- repos.push({
67
- name,
68
- path: rc?.path || name,
69
- });
70
- }
71
- return repos.length > 0 ? repos : [{ name: projectDir.split('/').pop() || 'project', path: '.' }];
72
- }
73
- catch (err) {
74
- console.warn('[Git API] Failed to parse repos.yaml:', err);
75
- const dirName = projectDir.split('/').pop() || 'project';
76
- return [{ name: dirName, path: '.' }];
77
- }
78
- }
79
- /**
80
- * Get git status for all configured repos (sync - blocks event loop, use getAllReposGitInfoAsync when possible)
81
- */
82
- export function getAllReposGitInfo(projectDir) {
83
- const repos = getReposFromConfig(projectDir);
84
- return repos.map(repo => {
85
- const repoPath = join(projectDir, repo.path);
86
- const gitInfo = getGitInfo(repoPath);
87
- return {
88
- name: repo.name,
89
- path: repo.path,
90
- branch: gitInfo?.branch || 'unknown',
91
- clean: gitInfo?.clean ?? true,
92
- ahead: gitInfo?.ahead ?? null,
93
- behind: gitInfo?.behind ?? null,
94
- developBehind: gitInfo?.developBehind ?? null,
95
- dirtyFiles: gitInfo?.dirtyFiles ?? [],
96
- };
97
- });
98
- }
99
- /**
100
- * Get git status for all configured repos (async - does not block event loop)
101
- */
102
- export async function getAllReposGitInfoAsync(projectDir) {
103
- const repos = getReposFromConfig(projectDir);
104
- const results = await Promise.all(repos.map(async (repo) => {
105
- const repoPath = join(projectDir, repo.path);
106
- const gitInfo = await getGitInfoAsync(repoPath);
107
- return {
108
- name: repo.name,
109
- path: repo.path,
110
- branch: gitInfo?.branch || 'unknown',
111
- clean: gitInfo?.clean ?? true,
112
- ahead: gitInfo?.ahead ?? null,
113
- behind: gitInfo?.behind ?? null,
114
- developBehind: gitInfo?.developBehind ?? null,
115
- dirtyFiles: gitInfo?.dirtyFiles ?? [],
116
- };
117
- }));
118
- return results;
119
- }
120
- // Get git status for project (sync - blocks event loop)
121
- export function getGitInfo(projectDir) {
122
- try {
123
- // Get current branch
124
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
125
- cwd: projectDir,
126
- encoding: 'utf-8',
127
- }).trim();
128
- // Get dirty files using --porcelain for parseable output
129
- let dirtyFiles = [];
130
- let clean = true;
131
- try {
132
- const statusOutput = execSync('git status --porcelain', {
133
- cwd: projectDir,
134
- encoding: 'utf-8',
135
- }).trim();
136
- if (statusOutput) {
137
- clean = false;
138
- dirtyFiles = statusOutput.split('\n').map(line => {
139
- const status = line.substring(0, 2).trim() || '?';
140
- const path = line.substring(3);
141
- return { status, path };
142
- });
143
- }
144
- }
145
- catch {
146
- // Fall back to diff-index check if porcelain fails
147
- try {
148
- execSync('git diff-index --quiet HEAD --', {
149
- cwd: projectDir,
150
- encoding: 'utf-8',
151
- });
152
- clean = true;
153
- }
154
- catch {
155
- clean = false;
156
- }
157
- }
158
- // Get ahead/behind counts (suppress stderr for branches without upstream)
159
- let ahead = null;
160
- let behind = null;
161
- try {
162
- const aheadOutput = execSync('git rev-list --count @{u}..HEAD', {
163
- cwd: projectDir,
164
- encoding: 'utf-8',
165
- stdio: ['pipe', 'pipe', 'pipe'],
166
- });
167
- ahead = parseInt(aheadOutput.trim(), 10);
168
- const behindOutput = execSync('git rev-list --count HEAD..@{u}', {
169
- cwd: projectDir,
170
- encoding: 'utf-8',
171
- stdio: ['pipe', 'pipe', 'pipe'],
172
- });
173
- behind = parseInt(behindOutput.trim(), 10);
174
- }
175
- catch {
176
- // No upstream configured - leave as null
177
- }
178
- // Get commits that origin/develop has that current branch doesn't
179
- let developBehind = null;
180
- try {
181
- const developBehindOutput = execSync('git rev-list --count HEAD..origin/develop', {
182
- cwd: projectDir,
183
- encoding: 'utf-8',
184
- stdio: ['pipe', 'pipe', 'pipe'],
185
- });
186
- developBehind = parseInt(developBehindOutput.trim(), 10);
187
- }
188
- catch {
189
- // origin/develop doesn't exist - leave as null
190
- }
191
- return { branch, clean, ahead, behind, dirtyFiles, developBehind };
192
- }
193
- catch (error) {
194
- // Not a git repo or git command failed - return null gracefully
195
- // Handles: not a git repository, EPIPE, ENOENT, etc.
196
- const errorMessage = error instanceof Error ? error.message : String(error);
197
- const errorCode = error?.code;
198
- // Log non-trivial errors for debugging but don't crash
199
- if (!errorMessage.includes('not a git repository')) {
200
- console.warn(`getGitInfo failed (${errorCode || 'unknown'}): ${errorMessage}`);
201
- }
202
- return null;
203
- }
204
- }
205
- /**
206
- * Get git status for project (async - does not block event loop)
207
- * This should be preferred over getGitInfo for WebSocket broadcasts and polling
208
- * Uses a per-repo mutex to prevent git lock conflicts from concurrent operations
209
- */
210
- export async function getGitInfoAsync(projectDir) {
211
- // Acquire lock to prevent concurrent git operations on the same repo
212
- const releaseLock = await acquireRepoLock(projectDir);
213
- try {
214
- // Fetch latest refs from remote (quiet, no output)
215
- // This ensures ahead/behind counts are accurate against remote state
216
- try {
217
- await execAsync('git fetch --quiet', {
218
- cwd: projectDir,
219
- encoding: 'utf-8',
220
- timeout: 10000, // 10s timeout for network operation
221
- });
222
- }
223
- catch {
224
- // Fetch failed (offline, no remote, etc.) - continue with local refs
225
- }
226
- // Get current branch
227
- const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD', {
228
- cwd: projectDir,
229
- encoding: 'utf-8',
230
- });
231
- const branch = branchOutput.trim();
232
- // Get dirty files using --porcelain for parseable output
233
- let dirtyFiles = [];
234
- let clean = true;
235
- try {
236
- const { stdout: statusOutput } = await execAsync('git status --porcelain', {
237
- cwd: projectDir,
238
- encoding: 'utf-8',
239
- });
240
- if (statusOutput.trim()) {
241
- clean = false;
242
- dirtyFiles = statusOutput.trim().split('\n').map(line => {
243
- const status = line.substring(0, 2).trim() || '?';
244
- const path = line.substring(3);
245
- return { status, path };
246
- });
247
- }
248
- }
249
- catch {
250
- // Fall back to diff-index check if porcelain fails
251
- try {
252
- await execAsync('git diff-index --quiet HEAD --', {
253
- cwd: projectDir,
254
- encoding: 'utf-8',
255
- });
256
- clean = true;
257
- }
258
- catch {
259
- clean = false;
260
- }
261
- }
262
- // Get ahead/behind counts vs tracking branch
263
- let ahead = null;
264
- let behind = null;
265
- try {
266
- const { stdout: aheadOutput } = await execAsync('git rev-list --count @{u}..HEAD', {
267
- cwd: projectDir,
268
- encoding: 'utf-8',
269
- });
270
- ahead = parseInt(aheadOutput.trim(), 10);
271
- const { stdout: behindOutput } = await execAsync('git rev-list --count HEAD..@{u}', {
272
- cwd: projectDir,
273
- encoding: 'utf-8',
274
- });
275
- behind = parseInt(behindOutput.trim(), 10);
276
- }
277
- catch {
278
- // No upstream configured - leave as null
279
- }
280
- // Get commits that origin/develop has that current branch doesn't
281
- // This alerts when develop has moved ahead (work done in another clone)
282
- let developBehind = null;
283
- try {
284
- const { stdout: developBehindOutput } = await execAsync('git rev-list --count HEAD..origin/develop', { cwd: projectDir, encoding: 'utf-8' });
285
- developBehind = parseInt(developBehindOutput.trim(), 10);
286
- }
287
- catch {
288
- // origin/develop doesn't exist or other error - leave as null
289
- }
290
- releaseLock();
291
- return { branch, clean, ahead, behind, dirtyFiles, developBehind };
292
- }
293
- catch (error) {
294
- releaseLock();
295
- // Not a git repo or git command failed - return null gracefully
296
- const errorMessage = error instanceof Error ? error.message : String(error);
297
- const errorCode = error?.code;
298
- // Log non-trivial errors for debugging but don't crash
299
- if (!errorMessage.includes('not a git repository')) {
300
- console.warn(`getGitInfoAsync failed (${errorCode || 'unknown'}): ${errorMessage}`);
301
- }
302
- return null;
303
- }
304
- }
305
- // Callback for forcing git refresh (set by websocket.ts)
306
- let forceRefreshCallback = null;
307
- export function setForceRefreshCallback(callback) {
308
- forceRefreshCallback = callback;
309
- }
310
- // Create git API router
311
- export function createGitRouter(getProjectDir) {
312
- const router = Router();
313
- // Git API - POST to force refresh (debugging/manual trigger)
314
- router.post('/refresh', async (_req, res) => {
315
- const projectDir = getProjectDir();
316
- console.log('[Git API] POST /refresh called, projectDir:', projectDir);
317
- if (!detectPennyfarthingProject(projectDir)) {
318
- console.log('[Git API] Not a Pennyfarthing project');
319
- return res.status(404).json({ error: 'Not a Pennyfarthing project' });
320
- }
321
- if (forceRefreshCallback) {
322
- console.log('[Git API] Calling forceRefreshCallback...');
323
- await forceRefreshCallback(projectDir);
324
- console.log('[Git API] forceRefreshCallback complete');
325
- res.json({ success: true, message: 'Git cache refreshed and broadcast sent' });
326
- }
327
- else {
328
- console.log('[Git API] No forceRefreshCallback registered!');
329
- res.status(500).json({ error: 'Refresh callback not registered' });
330
- }
331
- });
332
- // Git API - GET current git status (async to avoid blocking event loop)
333
- router.get('/', async (_req, res) => {
334
- const projectDir = getProjectDir();
335
- if (!detectPennyfarthingProject(projectDir)) {
336
- return res.status(404).json({ error: 'Not a Pennyfarthing project' });
337
- }
338
- const gitInfo = await getGitInfoAsync(projectDir);
339
- if (!gitInfo) {
340
- return res.status(404).json({ error: 'Not a git repository' });
341
- }
342
- res.json(gitInfo);
343
- });
344
- // Git API - GET status for all configured repos (async to avoid blocking event loop)
345
- router.get('/all', async (_req, res) => {
346
- const projectDir = getProjectDir();
347
- if (!detectPennyfarthingProject(projectDir)) {
348
- return res.status(404).json({ error: 'Not a Pennyfarthing project' });
349
- }
350
- const allReposInfo = await getAllReposGitInfoAsync(projectDir);
351
- res.json(allReposInfo);
352
- });
353
- return router;
354
- }
1
+ // Re-export from @pennyfarthing/core (Story 98-17)
2
+ export * from '@pennyfarthing/core/dist/server/api/git.js';
355
3
  //# sourceMappingURL=git.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/api/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/api/git.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,cAAc,4CAA4C,CAAC"}
@@ -1,3 +1,2 @@
1
- import { Router } from 'express';
2
- export declare function createHealthScoreRouter(getProjectDir: () => string): Router;
1
+ export * from '@pennyfarthing/core/dist/server/api/health-score.js';
3
2
  //# sourceMappingURL=health-score.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"health-score.d.ts","sourceRoot":"","sources":["../../src/api/health-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,MAAM,GAAG,MAAM,CAgD3E"}
1
+ {"version":3,"file":"health-score.d.ts","sourceRoot":"","sources":["../../src/api/health-score.ts"],"names":[],"mappings":"AACA,cAAc,qDAAqD,CAAC"}
@@ -1,47 +1,3 @@
1
- import { Router } from 'express';
2
- import { execFile } from 'child_process';
3
- import { join } from 'path';
4
- export function createHealthScoreRouter(getProjectDir) {
5
- const router = Router();
6
- router.get('/', (req, res) => {
7
- const projectDir = getProjectDir();
8
- const args = ['-m', 'pennyfarthing_scripts.healthscore', 'analyze', '--format', 'json', '--no-cache'];
9
- const pythonPath = join(projectDir, 'pennyfarthing');
10
- console.log('[HealthScore] Starting analysis, cwd=%s, PYTHONPATH=%s', pythonPath, pythonPath);
11
- execFile('python3', args, {
12
- cwd: pythonPath,
13
- env: { ...process.env, PYTHONPATH: pythonPath },
14
- timeout: 60000,
15
- }, (err, stdout, stderr) => {
16
- // Always log stderr — it contains per-dimension probe logs
17
- if (stderr) {
18
- console.log('[HealthScore] Python stderr:\n%s', stderr);
19
- }
20
- if (err) {
21
- console.error('[HealthScore] Analysis failed:', err.message);
22
- res.status(500).json({
23
- success: false,
24
- error: stderr || err.message,
25
- });
26
- return;
27
- }
28
- try {
29
- const data = JSON.parse(stdout);
30
- const dims = data.dimensions || [];
31
- const scored = dims.filter((d) => d.score !== null).length;
32
- console.log('[HealthScore] Success: composite=%.1f, %d/%d dimensions scored', data.composite_score, scored, dims.length);
33
- res.json(data);
34
- }
35
- catch (parseErr) {
36
- console.error('[HealthScore] JSON parse failed:', parseErr);
37
- console.error('[HealthScore] Raw stdout: %s', stdout.slice(0, 500));
38
- res.status(500).json({
39
- success: false,
40
- error: 'Failed to parse health score output',
41
- });
42
- }
43
- });
44
- });
45
- return router;
46
- }
1
+ // Re-export from @pennyfarthing/core (Story 98-17)
2
+ export * from '@pennyfarthing/core/dist/server/api/health-score.js';
47
3
  //# sourceMappingURL=health-score.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health-score.js","sourceRoot":"","sources":["../../src/api/health-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,UAAU,uBAAuB,CAAC,aAA2B;IACjE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,mCAAmC,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACtG,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAErD,OAAO,CAAC,GAAG,CAAC,wDAAwD,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;QAE9F,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE;YACxB,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE;YAC/C,OAAO,EAAE,KAAK;SACf,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACzB,2DAA2D;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,OAAO;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;gBACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAA2B,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;gBACrF,OAAO,CAAC,GAAG,CAAC,gEAAgE,EAC1E,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC7C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;YAAC,OAAO,QAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC;gBAC5D,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,qCAAqC;iBAC7C,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"health-score.js","sourceRoot":"","sources":["../../src/api/health-score.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,cAAc,qDAAqD,CAAC"}