@storyshelf/app 0.7.0 → 0.9.0-next-d2cc082

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/app-types.d.mts +1 -3
  2. package/dist/asset-manifest.mjs +1 -2
  3. package/dist/assets/htmx.mjs +1 -2
  4. package/dist/assets/mark.mjs +1 -2
  5. package/dist/boot-tasks.mjs +1 -2
  6. package/dist/build-state-flags.mjs +1 -2
  7. package/dist/build-state-setup.mjs +1 -2
  8. package/dist/capture-alerts.mjs +1 -2
  9. package/dist/capture-process.mjs +1 -2
  10. package/dist/capture-setup.mjs +1 -2
  11. package/dist/connections.mjs +1 -2
  12. package/dist/consumer-setup.mjs +1 -2
  13. package/dist/credential-keys.mjs +1 -2
  14. package/dist/credentials.mjs +1 -2
  15. package/dist/design-events.mjs +71 -0
  16. package/dist/design-events.mjs.map +1 -0
  17. package/dist/git-status.mjs +1 -2
  18. package/dist/hidden-data.mjs +1 -2
  19. package/dist/index.d.mts +0 -2
  20. package/dist/index.mjs +2 -3
  21. package/dist/insights/budget.mjs +1 -2
  22. package/dist/insights/deps.mjs +1 -2
  23. package/dist/insights/errors.mjs +1 -2
  24. package/dist/insights/health-panel.mjs +0 -1
  25. package/dist/insights/job.mjs +1 -2
  26. package/dist/insights/load-health.mjs +1 -2
  27. package/dist/insights/load-triage.mjs +1 -2
  28. package/dist/insights/panel.mjs +1 -2
  29. package/dist/insights/request.mjs +1 -2
  30. package/dist/insights/stale.mjs +1 -2
  31. package/dist/insights/usage-report.mjs +1 -2
  32. package/dist/insights/view.mjs +1 -2
  33. package/dist/job-canceller.mjs +1 -2
  34. package/dist/job-queue.mjs +1 -2
  35. package/dist/jobs-setup.mjs +1 -2
  36. package/dist/lifecycle.mjs +2 -3
  37. package/dist/lifecycle.mjs.map +1 -1
  38. package/dist/middleware/auth-gate.mjs +1 -2
  39. package/dist/middleware/csrf.mjs +1 -2
  40. package/dist/middleware/rate-limit.mjs +1 -2
  41. package/dist/middleware/request-log.mjs +1 -2
  42. package/dist/middleware/require-review.mjs +1 -2
  43. package/dist/middleware/require-testing.mjs +1 -2
  44. package/dist/middleware/server-timing.mjs +1 -2
  45. package/dist/middleware/setup-gate.mjs +1 -2
  46. package/dist/middleware/store-scope.mjs +1 -2
  47. package/dist/notifications-pause.mjs +1 -2
  48. package/dist/notify.d.mts +1 -3
  49. package/dist/notify.mjs +5 -3
  50. package/dist/notify.mjs.map +1 -1
  51. package/dist/pages/a11y-violations.mjs +1 -2
  52. package/dist/pages/admin-ai.mjs +1 -2
  53. package/dist/pages/admin-system-origin.mjs +19 -10
  54. package/dist/pages/admin-system-origin.mjs.map +1 -1
  55. package/dist/pages/admin-system-targets.mjs +1 -2
  56. package/dist/pages/admin-system.mjs +1 -2
  57. package/dist/pages/build-detail.mjs +1 -2
  58. package/dist/pages/build-diff-actions.mjs +1 -2
  59. package/dist/pages/build-diff-comments.mjs +1 -2
  60. package/dist/pages/build-diff-default.mjs +53 -0
  61. package/dist/pages/build-diff-default.mjs.map +1 -0
  62. package/dist/pages/build-diff-environment.mjs +34 -5
  63. package/dist/pages/build-diff-environment.mjs.map +1 -1
  64. package/dist/pages/build-diff-header.mjs +1 -2
  65. package/dist/pages/build-diff-insight.mjs +1 -2
  66. package/dist/pages/build-diff-model.mjs +20 -3
  67. package/dist/pages/build-diff-model.mjs.map +1 -1
  68. package/dist/pages/build-diff-nav.mjs +1 -2
  69. package/dist/pages/build-diff-reference.mjs +84 -0
  70. package/dist/pages/build-diff-reference.mjs.map +1 -0
  71. package/dist/pages/build-diff-shortcuts.mjs +1 -2
  72. package/dist/pages/build-diff-stale.mjs +1 -2
  73. package/dist/pages/build-diff-usage.mjs +1 -2
  74. package/dist/pages/build-diff-viewer.mjs +38 -12
  75. package/dist/pages/build-diff-viewer.mjs.map +1 -1
  76. package/dist/pages/build-diff.mjs +6 -12
  77. package/dist/pages/build-diff.mjs.map +1 -1
  78. package/dist/pages/build-tests.mjs +1 -2
  79. package/dist/pages/component-detail.mjs +1 -2
  80. package/dist/pages/component-stories.mjs +1 -2
  81. package/dist/pages/compute-jobs.mjs +1 -2
  82. package/dist/pages/design-links.mjs +1 -2
  83. package/dist/pages/environment-change.mjs +16 -4
  84. package/dist/pages/environment-change.mjs.map +1 -1
  85. package/dist/pages/health-panel.mjs +1 -2
  86. package/dist/pages/invite.mjs +1 -2
  87. package/dist/pages/label-detail.mjs +1 -2
  88. package/dist/pages/library-grid.mjs +1 -2
  89. package/dist/pages/library-model.mjs +1 -2
  90. package/dist/pages/library-snapshots.mjs +1 -2
  91. package/dist/pages/library.mjs +1 -2
  92. package/dist/pages/login.mjs +1 -2
  93. package/dist/pages/notifications-paused.mjs +1 -2
  94. package/dist/pages/passkey-ceremony.mjs +1 -2
  95. package/dist/pages/profile.mjs +1 -2
  96. package/dist/pages/project-builds-table.mjs +1 -2
  97. package/dist/pages/project-builds.mjs +1 -2
  98. package/dist/pages/project-create.mjs +1 -2
  99. package/dist/pages/project-settings.mjs +1 -2
  100. package/dist/pages/projects-card.mjs +1 -2
  101. package/dist/pages/projects.mjs +1 -2
  102. package/dist/pages/review-changeset.mjs +1 -2
  103. package/dist/pages/review-comments.mjs +1 -2
  104. package/dist/pages/review-verdict.mjs +1 -2
  105. package/dist/pages/root.mjs +1 -2
  106. package/dist/pages/settings-ai.mjs +1 -2
  107. package/dist/pages/settings-capture.mjs +1 -2
  108. package/dist/pages/settings-design-credential.mjs +1 -2
  109. package/dist/pages/settings-design-links.mjs +1 -2
  110. package/dist/pages/settings-design.mjs +1 -2
  111. package/dist/pages/settings-general.mjs +1 -2
  112. package/dist/pages/settings-labels.mjs +1 -2
  113. package/dist/pages/settings-links.mjs +1 -2
  114. package/dist/pages/settings-members.mjs +1 -2
  115. package/dist/pages/settings-notifications-git.mjs +1 -2
  116. package/dist/pages/settings-notifications.mjs +1 -2
  117. package/dist/pages/settings-tests.mjs +1 -2
  118. package/dist/pages/settings-tokens.mjs +1 -2
  119. package/dist/pages/settings-webhooks.mjs +1 -2
  120. package/dist/pages/storybook.mjs +1 -2
  121. package/dist/pages/target-choices.mjs +1 -2
  122. package/dist/publish-setup.mjs +1 -2
  123. package/dist/retention-timer.mjs +10 -11
  124. package/dist/retention-timer.mjs.map +1 -1
  125. package/dist/review-events.mjs +1 -2
  126. package/dist/routers/admin-pages.mjs +1 -2
  127. package/dist/routers/admin-public-origin.mjs +10 -3
  128. package/dist/routers/admin-public-origin.mjs.map +1 -1
  129. package/dist/routers/admin.mjs +8 -4
  130. package/dist/routers/admin.mjs.map +1 -1
  131. package/dist/routers/assets.mjs +1 -2
  132. package/dist/routers/attempts.mjs +1 -2
  133. package/dist/routers/auth-sync.mjs +1 -2
  134. package/dist/routers/auth.mjs +1 -2
  135. package/dist/routers/baseline-guard.mjs +2 -3
  136. package/dist/routers/baseline-guard.mjs.map +1 -1
  137. package/dist/routers/baseline-reference.mjs +72 -0
  138. package/dist/routers/baseline-reference.mjs.map +1 -0
  139. package/dist/routers/baselines.handlers.mjs +1 -2
  140. package/dist/routers/baselines.mjs +1 -2
  141. package/dist/routers/build-cancel.mjs +1 -2
  142. package/dist/routers/build-changeset.mjs +1 -2
  143. package/dist/routers/build-reviews.handlers.mjs +1 -2
  144. package/dist/routers/build-reviews.mjs +1 -2
  145. package/dist/routers/builds.handlers.mjs +23 -9
  146. package/dist/routers/builds.handlers.mjs.map +1 -1
  147. package/dist/routers/builds.mjs +7 -3
  148. package/dist/routers/builds.mjs.map +1 -1
  149. package/dist/routers/capture-cache.mjs +29 -0
  150. package/dist/routers/capture-cache.mjs.map +1 -0
  151. package/dist/routers/capture-config.mjs +1 -2
  152. package/dist/routers/comments.mjs +1 -2
  153. package/dist/routers/comparison-image.mjs +29 -0
  154. package/dist/routers/comparison-image.mjs.map +1 -0
  155. package/dist/routers/component-catalog.handlers.mjs +1 -2
  156. package/dist/routers/component.handlers.mjs +1 -2
  157. package/dist/routers/connections.mjs +1 -2
  158. package/dist/routers/design-connect.handlers.mjs +1 -2
  159. package/dist/routers/design.handlers.mjs +8 -2
  160. package/dist/routers/design.handlers.mjs.map +1 -1
  161. package/dist/routers/flash.mjs +1 -2
  162. package/dist/routers/health-report.mjs +1 -2
  163. package/dist/routers/health.mjs +1 -2
  164. package/dist/routers/helpers.mjs +1 -2
  165. package/dist/routers/htmx.mjs +1 -2
  166. package/dist/routers/insights-ui.mjs +1 -2
  167. package/dist/routers/insights.handlers.mjs +1 -2
  168. package/dist/routers/insights.mjs +1 -2
  169. package/dist/routers/labels.mjs +1 -2
  170. package/dist/routers/links.handlers.mjs +1 -2
  171. package/dist/routers/links.mjs +1 -2
  172. package/dist/routers/media.mjs +14 -5
  173. package/dist/routers/media.mjs.map +1 -1
  174. package/dist/routers/members.mjs +1 -2
  175. package/dist/routers/notification-channels.mjs +1 -2
  176. package/dist/routers/notification-subscriptions.mjs +1 -2
  177. package/dist/routers/oauth-state.mjs +1 -2
  178. package/dist/routers/preview-base.mjs +1 -2
  179. package/dist/routers/preview-token.mjs +1 -2
  180. package/dist/routers/profile.mjs +1 -2
  181. package/dist/routers/projects.mjs +1 -2
  182. package/dist/routers/publish-upload.mjs +19 -12
  183. package/dist/routers/publish-upload.mjs.map +1 -1
  184. package/dist/routers/published-access.mjs +1 -2
  185. package/dist/routers/published-compression.mjs +109 -0
  186. package/dist/routers/published-compression.mjs.map +1 -0
  187. package/dist/routers/published-files.mjs +26 -9
  188. package/dist/routers/published-files.mjs.map +1 -1
  189. package/dist/routers/review-forms.mjs +1 -2
  190. package/dist/routers/review-next.mjs +1 -2
  191. package/dist/routers/review-section.handlers.mjs +1 -2
  192. package/dist/routers/review-switch-off.mjs +1 -2
  193. package/dist/routers/schemas.mjs +1 -2
  194. package/dist/routers/scoped-models.mjs +1 -2
  195. package/dist/routers/settings-ai.mjs +1 -2
  196. package/dist/routers/settings-capture.mjs +1 -2
  197. package/dist/routers/settings-design.mjs +1 -2
  198. package/dist/routers/settings-general.mjs +1 -2
  199. package/dist/routers/settings-git-channel.mjs +1 -2
  200. package/dist/routers/settings-labels.mjs +1 -2
  201. package/dist/routers/settings-links.mjs +1 -2
  202. package/dist/routers/settings-members.mjs +1 -2
  203. package/dist/routers/settings-notifications.mjs +1 -2
  204. package/dist/routers/settings-tokens.mjs +1 -2
  205. package/dist/routers/settings-webhooks.mjs +1 -2
  206. package/dist/routers/settings.handlers.mjs +1 -2
  207. package/dist/routers/settings.mjs +1 -2
  208. package/dist/routers/signed-storybook.mjs +5 -3
  209. package/dist/routers/signed-storybook.mjs.map +1 -1
  210. package/dist/routers/snapshot-groups.mjs +1 -2
  211. package/dist/routers/snapshots.mjs +1 -2
  212. package/dist/routers/storybook.mjs +21 -17
  213. package/dist/routers/storybook.mjs.map +1 -1
  214. package/dist/routers/tokens.mjs +1 -2
  215. package/dist/routers/ui.mjs +4 -2
  216. package/dist/routers/ui.mjs.map +1 -1
  217. package/dist/routers/webhooks.mjs +1 -2
  218. package/dist/routers/well-known.mjs +1 -2
  219. package/dist/routes/api-routes.mjs +1 -2
  220. package/dist/routes/classification.mjs +1 -2
  221. package/dist/routes/openapi-classes.mjs +1 -2
  222. package/dist/routes/page-routes.mjs +2 -3
  223. package/dist/routes/page-routes.mjs.map +1 -1
  224. package/dist/runtime.mjs +1 -2
  225. package/dist/serverless.mjs +1 -2
  226. package/dist/store.mjs +1 -2
  227. package/dist/targets.mjs +1 -2
  228. package/dist/ui/avatar.mjs +1 -2
  229. package/dist/ui/buttons.mjs +1 -2
  230. package/dist/ui/code-block.mjs +1 -2
  231. package/dist/ui/compare-stage.mjs +86 -54
  232. package/dist/ui/compare-stage.mjs.map +1 -1
  233. package/dist/ui/csrf-field.mjs +1 -2
  234. package/dist/ui/css.mjs +1 -2
  235. package/dist/ui/design-reference.mjs +1 -2
  236. package/dist/ui/document.mjs +1 -2
  237. package/dist/ui/dropdown.mjs +1 -2
  238. package/dist/ui/feedback.mjs +1 -2
  239. package/dist/ui/filter-input.mjs +1 -2
  240. package/dist/ui/forms.mjs +1 -2
  241. package/dist/ui/icons/icon.mjs +1 -2
  242. package/dist/ui/icons/paths.mjs +1 -2
  243. package/dist/ui/icons/sprite.mjs +1 -2
  244. package/dist/ui/kbd.mjs +1 -2
  245. package/dist/ui/layout.mjs +1 -2
  246. package/dist/ui/preview-embed.mjs +1 -2
  247. package/dist/ui/progress.mjs +1 -2
  248. package/dist/ui/segmented.mjs +1 -2
  249. package/dist/ui/shell/account.mjs +1 -2
  250. package/dist/ui/shell/bare.mjs +1 -2
  251. package/dist/ui/shell/boot-script.mjs +1 -2
  252. package/dist/ui/shell/client-script.mjs +1 -2
  253. package/dist/ui/shell/nav.mjs +1 -2
  254. package/dist/ui/shell/review-script.mjs +17 -3
  255. package/dist/ui/shell/review-script.mjs.map +1 -1
  256. package/dist/ui/shell/sidebar.mjs +1 -2
  257. package/dist/ui/shell/topbar.mjs +1 -2
  258. package/dist/ui/stacks.mjs +1 -2
  259. package/dist/ui/styles/base.mjs +1 -2
  260. package/dist/ui/styles/behavior.mjs +1 -2
  261. package/dist/ui/styles/review-layout.mjs +1 -2
  262. package/dist/ui/styles/review.mjs +1 -2
  263. package/dist/ui/styles/tokens.mjs +1 -2
  264. package/dist/ui/styles.mjs +1 -2
  265. package/dist/ui/subnav.mjs +1 -2
  266. package/dist/ui/table.mjs +1 -2
  267. package/dist/ui/theme.mjs +1 -2
  268. package/dist/ui/thumbnail.mjs +1 -2
  269. package/dist/ui/time.mjs +1 -2
  270. package/package.json +9 -18
@@ -5,11 +5,10 @@ import { AdapterSetupResult } from "@storyshelf/core/adapter/setup";
5
5
  import { ShelfConfig, UIConfig } from "@storyshelf/core/config";
6
6
  import { NotifierProvider } from "@storyshelf/core/adapter/notifier";
7
7
  import { AuthUser } from "@storyshelf/core/types";
8
+ import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
8
9
  import { Logger, createShelfLogger } from "@storyshelf/core/logger";
9
10
  import { CaptureQueue } from "@storyshelf/core/adapter/capture-queue";
10
- import { DatabaseAdapter } from "@storyshelf/core/adapter/database";
11
11
  import { StorageAdapter } from "@storyshelf/core/adapter/storage";
12
- //#region src/app-types.d.ts
13
12
  /** Per-request shelf context (adapters, config, user, capture queue). */
14
13
  interface ShelfContext {
15
14
  requestId?: string;
@@ -47,6 +46,5 @@ interface ShelfLifecycle {
47
46
  type ShelfApp = ShelfRouter & {
48
47
  readonly lifecycle: ShelfLifecycle;
49
48
  };
50
- //#endregion
51
49
  export { ShelfApp, ShelfContext, ShelfLifecycle, ShelfRouter };
52
50
  //# sourceMappingURL=app-types.d.mts.map
@@ -5,7 +5,7 @@ import { contentHash, iconSprite, iconSpriteHash, iconSpriteHref } from "./ui/ic
5
5
  import { htmxSource } from "./assets/htmx.mjs";
6
6
  import { markSource } from "./assets/mark.mjs";
7
7
  import { clientScript } from "./ui/shell/client-script.mjs";
8
- //#region src/asset-manifest.ts
8
+ // src/asset-manifest.ts
9
9
  /**
10
10
  * Static assets with content-addressed URLs. A URL that embeds the content
11
11
  * hash may be cached forever (`immutable`): changing the file changes the
@@ -43,7 +43,6 @@ const assetManifest = {
43
43
  href: `/assets/mark-${markHash}.svg`
44
44
  }
45
45
  };
46
- //#endregion
47
46
  export { assetManifest };
48
47
 
49
48
  //# sourceMappingURL=asset-manifest.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/assets/htmx.ts
4
+ // src/assets/htmx.ts
5
5
  const htmxSource = String.raw`(function (e, t) {
6
6
  if (typeof define === "function" && define.amd) {
7
7
  define([], t);
@@ -3307,7 +3307,6 @@ const htmxSource = String.raw`(function (e, t) {
3307
3307
  })();
3308
3308
  });
3309
3309
  `;
3310
- //#endregion
3311
3310
  export { htmxSource };
3312
3311
 
3313
3312
  //# sourceMappingURL=htmx.mjs.map
@@ -1,10 +1,9 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/assets/mark.ts
4
+ // src/assets/mark.ts
5
5
  /** The StoryShelf brand mark (an SVG): the favicon and the default sidebar logo. */
6
6
  const markSource = String.raw`<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64' viewBox='0 0 64 64' role='img' aria-label='StoryShelf'><rect width='64' height='64' rx='14' fill='#1d5fcf'/><path d='M15 11 H49 A4 4 0 0 1 53 15 V15 A2 2 0 0 1 51 17 H13 A2 2 0 0 1 11 15 V15 A4 4 0 0 1 15 11 Z' fill='#ffffff'/><path d='M13 29 H51 A2 2 0 0 1 53 31 V33 A2 2 0 0 1 51 35 H13 A2 2 0 0 1 11 33 V31 A2 2 0 0 1 13 29 Z' fill='#ffffff'/><path d='M13 47 H51 A2 2 0 0 1 53 49 V49 A4 4 0 0 1 49 53 H15 A4 4 0 0 1 11 49 V49 A2 2 0 0 1 13 47 Z' fill='#ffffff'/><path d='M16 19 H16 A2 2 0 0 1 18 21 V27 A2 2 0 0 1 16 29 H16 A2 2 0 0 1 14 27 V21 A2 2 0 0 1 16 19 Z' fill='#ffffff'/><path d='M22 21 H22 A2 2 0 0 1 24 23 V27 A2 2 0 0 1 22 29 H22 A2 2 0 0 1 20 27 V23 A2 2 0 0 1 22 21 Z' fill='#ffffff'/><path d='M28 23 H28 A2 2 0 0 1 30 25 V27 A2 2 0 0 1 28 29 H28 A2 2 0 0 1 26 27 V25 A2 2 0 0 1 28 23 Z' fill='#ffffff'/><path d='M48 37 H48 A2 2 0 0 1 50 39 V45 A2 2 0 0 1 48 47 H48 A2 2 0 0 1 46 45 V39 A2 2 0 0 1 48 37 Z' fill='#ffffff'/><path d='M42 39 H42 A2 2 0 0 1 44 41 V45 A2 2 0 0 1 42 47 H42 A2 2 0 0 1 40 45 V41 A2 2 0 0 1 42 39 Z' fill='#ffffff'/><path d='M36 41 H36 A2 2 0 0 1 38 43 V45 A2 2 0 0 1 36 47 H36 A2 2 0 0 1 34 45 V43 A2 2 0 0 1 36 41 Z' fill='#ffffff'/></svg>`;
7
- //#endregion
8
7
  export { markSource };
9
8
 
10
9
  //# sourceMappingURL=mark.mjs.map
@@ -6,7 +6,7 @@ import { startConsumer, trackBackground } from "./lifecycle.mjs";
6
6
  import { checkCredentialsAfterSetup } from "./credentials.mjs";
7
7
  import { logHostingOnlyMode } from "./hidden-data.mjs";
8
8
  import { requestOpenBuildStates, sweepOrphanedScratch } from "@storyshelf/core/capture";
9
- //#region src/boot-tasks.ts
9
+ // src/boot-tasks.ts
10
10
  /**
11
11
  * Boot-time work that runs once adapters are ready: the job consumer starts (there is no boot sweep
12
12
  * of builds left `capturing`: leases expire and jobs are redelivered, so a second instance can
@@ -74,7 +74,6 @@ function sweepScratchOnBoot(cell, scratchDir, logger) {
74
74
  logger.warn({ err: error }, "scratch sweep failed");
75
75
  }));
76
76
  }
77
- //#endregion
78
77
  export { runBootTasks };
79
78
 
80
79
  //# sourceMappingURL=boot-tasks.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/build-state-flags.ts
4
+ // src/build-state-flags.ts
5
5
  /**
6
6
  * What decides which statuses a project's builds show: the instance's `testing` and the project's
7
7
  * review switch (a row without the column, from a hand-built table, counts as on, the default).
@@ -12,7 +12,6 @@ function buildStateFlags(testing, project) {
12
12
  review: project.reviewEnabled !== false
13
13
  };
14
14
  }
15
- //#endregion
16
15
  export { buildStateFlags };
17
16
 
18
17
  //# sourceMappingURL=build-state-flags.mjs.map
@@ -6,7 +6,7 @@ import { notifySystemWith } from "./notify.mjs";
6
6
  import { buildStateFlags } from "./build-state-flags.mjs";
7
7
  import { createBuildStatePublisher, createNotifyEnqueuer, createNotifyHandler, notifyExhausted } from "@storyshelf/core/capture";
8
8
  import { ProjectModel } from "@storyshelf/core/models";
9
- //#region src/build-state-setup.ts
9
+ // src/build-state-setup.ts
10
10
  /**
11
11
  * Build-state wiring (ADR 0014, decisions 5 and 7): the publisher every build transition calls and
12
12
  * the `notify` job kind behind it. On a host that polls the queue, a transition queues one durable
@@ -69,7 +69,6 @@ async function alertAdmins(options, runtime, failure) {
69
69
  message: `${failure.provider} channel of ${project?.slug ?? "a project"} could not show build ${failure.buildId}: ${failure.error}`
70
70
  });
71
71
  }
72
- //#endregion
73
72
  export { setupBuildState };
74
73
 
75
74
  //# sourceMappingURL=build-state-setup.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { notifyProjectWith, notifySystemWith } from "./notify.mjs";
5
5
  import { BuildModel, ProjectModel } from "@storyshelf/core/models";
6
- //#region src/capture-alerts.ts
6
+ // src/capture-alerts.ts
7
7
  /**
8
8
  * Builds already alerted about, keyed by the build's last update. A sharded build settles one job
9
9
  * per shard and every one of them sees the failed build; only the first alerts. A retry rewrites
@@ -40,7 +40,6 @@ async function notifyCaptureFailed(options, config, logger, buildId, publicOrigi
40
40
  status: "failed"
41
41
  }, `/builds/${buildId}`);
42
42
  }
43
- //#endregion
44
43
  export { alreadyAlerted, notifyCaptureFailed };
45
44
 
46
45
  //# sourceMappingURL=capture-alerts.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { DIFF_WORKERS_ENV, IMAGE_ENGINE_ENV } from "@storyshelf/core/diff";
5
5
  import { detectResources } from "@storyshelf/core/utils";
6
6
  import { CAPTURE_RETRIES_ENV, CAPTURE_SHARD_SIZE_ENV, canForkCaptureChild, createForkedCaptureHandler, decideCaptureProcess, forkCaptureChild } from "@storyshelf/core/capture";
7
- //#region src/capture-process.ts
7
+ // src/capture-process.ts
8
8
  /** Chooses between in-process and forked capture, and builds the forked handler. */
9
9
  /**
10
10
  * Whether to fork a capture child. `mode: "fork"` forces it (and fails if it cannot); `auto` forks
@@ -53,7 +53,6 @@ function createForkedHandler(deps) {
53
53
  logger: deps.logger
54
54
  });
55
55
  }
56
- //#endregion
57
56
  export { childEnvOf, createForkedHandler, shouldForkCapture };
58
57
 
59
58
  //# sourceMappingURL=capture-process.mjs.map
@@ -7,7 +7,7 @@ import { createForkedHandler, shouldForkCapture } from "./capture-process.mjs";
7
7
  import { DEFAULT_SCRATCH_DIR } from "@storyshelf/core/config";
8
8
  import { currentTraceparent } from "@storyshelf/observability";
9
9
  import { DEFAULT_RETRIES, captureDispatchDeps, createCaptureHandler, failCrashedCapture, isFinalAttempt } from "@storyshelf/core/capture";
10
- //#region src/capture-setup.ts
10
+ // src/capture-setup.ts
11
11
  /** Queue a build, continuing the active request trace when present. */
12
12
  function enqueuerFor(queue) {
13
13
  return async (buildId, reqId) => {
@@ -111,7 +111,6 @@ function alerting(inner, retries, alert) {
111
111
  ...inner.close ? { close: inner.close } : {}
112
112
  };
113
113
  }
114
- //#endregion
115
114
  export { setupCapture };
116
115
 
117
116
  //# sourceMappingURL=capture-setup.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { credentialKeys } from "./credential-keys.mjs";
5
5
  import { getStore } from "./store.mjs";
6
6
  import { ConnectionModel } from "@storyshelf/core/models";
7
- //#region src/connections.ts
7
+ // src/connections.ts
8
8
  /**
9
9
  * Services a user can connect their own account to. Today only design providers
10
10
  * offer OAuth; a future issue-tracker or notifier adapter that exposes
@@ -28,7 +28,6 @@ function canConnect() {
28
28
  const { authEnabled, user, config } = getStore();
29
29
  return authEnabled && Boolean(user) && Boolean(config.secret);
30
30
  }
31
- //#endregion
32
31
  export { canConnect, connectableServices, connectionModel, findConnectable };
33
32
 
34
33
  //# sourceMappingURL=connections.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { captureMetrics } from "@storyshelf/observability";
5
5
  import { createCaptureConsumer } from "@storyshelf/core/capture";
6
- //#region src/consumer-setup.ts
6
+ // src/consumer-setup.ts
7
7
  /**
8
8
  * The consumer of the app's queues (ADR 0006, decision 5): built when first started, so a host
9
9
  * that never starts one never touches the queue, and drained as a unit on teardown.
@@ -52,7 +52,6 @@ function jobMetrics() {
52
52
  else if (event.outcome === "failed") instruments.jobsFailed.add(1, attributes);
53
53
  } };
54
54
  }
55
- //#endregion
56
55
  export { combineConsumers, jobMetrics, lazyConsumer };
57
56
 
58
57
  //# sourceMappingURL=consumer-setup.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/credential-keys.ts
4
+ // src/credential-keys.ts
5
5
  /**
6
6
  * Key material for encrypted credentials: the current secret, plus
7
7
  * `previousSecret` as a decrypt-only fallback during a rotation. Not for
@@ -14,7 +14,6 @@ function credentialKeys(config) {
14
14
  };
15
15
  return config.secret;
16
16
  }
17
- //#endregion
18
17
  export { credentialKeys };
19
18
 
20
19
  //# sourceMappingURL=credential-keys.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { trackBackground } from "./lifecycle.mjs";
5
5
  import { probeCredentials, reencryptCredentials } from "@storyshelf/core/models";
6
- //#region src/credentials.ts
6
+ // src/credentials.ts
7
7
  /** Current/previous key pair for a probe, or null when no secret is configured. */
8
8
  function secretKeysOf(config) {
9
9
  if (!config.secret) return null;
@@ -51,7 +51,6 @@ function checkCredentialsAfterSetup(cell, db, config, logger) {
51
51
  logger.error({ err: error }, "credential check failed");
52
52
  }));
53
53
  }
54
- //#endregion
55
54
  export { checkCredentialsAfterSetup, checkCredentialsAtBoot, loadCredentialProbe, reencryptWithCurrent, secretKeysOf };
56
55
 
57
56
  //# sourceMappingURL=credentials.mjs.map
@@ -0,0 +1,71 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { credentialKeys } from "./credential-keys.mjs";
5
+ import { clearPaused, notificationOrigin, warnPaused } from "./notifications-pause.mjs";
6
+ import { notifyProjectWith } from "./notify.mjs";
7
+ import { designChange } from "@storyshelf/core/models";
8
+ import { emitWebhookEvent } from "@storyshelf/core/adapter/webhook-events";
9
+ import { createUrlBuilder } from "@storyshelf/core/urls";
10
+ // src/design-events.ts
11
+ /**
12
+ * `design:changed`: a design moved after its baseline was approved, or no longer exists. It rides
13
+ * the existing paths (signed webhooks and the notification fan-out) and is a normal subscribable
14
+ * topic: it is not default-on (see `notify.ts`), so only people who opted in hear about it.
15
+ *
16
+ * Sent once per (project, design node, design version) from the first health check that sees the
17
+ * change. The durable claim is `DesignNodeModel.claimChange`; with no confirmed public origin
18
+ * nothing is sent and nothing is claimed, so the change is still announced once an origin exists.
19
+ * There is no boot replay: an unannounced change waits for the next health check.
20
+ */
21
+ /** Event name of a design change. */
22
+ const DESIGN_CHANGED_EVENT = "design:changed";
23
+ /**
24
+ * Announce every observed design change not announced before. Never throws: a failure is logged
25
+ * and the next health check tries again.
26
+ */
27
+ async function announceDesignChangesWith(deps, nodes, project, observations) {
28
+ const changes = observations.flatMap((observation) => {
29
+ const change = observation.componentPath ? designChange(observation.node, observation.baselineVersion) : null;
30
+ return observation.node && observation.componentPath && change ? [{
31
+ ...observation,
32
+ node: observation.node,
33
+ componentPath: observation.componentPath,
34
+ change
35
+ }] : [];
36
+ });
37
+ if (changes.length === 0 || !await originConfirmed(deps)) return;
38
+ await Promise.all(changes.map(async (item) => {
39
+ try {
40
+ if (await nodes.claimChange(item.node, item.change)) await announce(deps, project, item);
41
+ } catch (error) {
42
+ deps.logger.warn({
43
+ err: error,
44
+ projectId: project.id
45
+ }, "design change not announced");
46
+ }
47
+ }));
48
+ }
49
+ async function originConfirmed(deps) {
50
+ if (await notificationOrigin(deps) === void 0) {
51
+ warnPaused(deps.logger, DESIGN_CHANGED_EVENT);
52
+ return false;
53
+ }
54
+ clearPaused(deps.logger);
55
+ return true;
56
+ }
57
+ async function announce(deps, project, item) {
58
+ const data = {
59
+ projectId: project.id,
60
+ componentPath: item.componentPath,
61
+ figmaUrl: item.url,
62
+ change: item.change.change,
63
+ designVersion: item.change.designVersion
64
+ };
65
+ await emitWebhookEvent(deps.db, { webhooks: deps.db.tables.webhooks }, project.id, DESIGN_CHANGED_EVENT, data, credentialKeys(deps.config), deps.logger);
66
+ const component = createUrlBuilder("").component(project.slug, item.componentPath);
67
+ await notifyProjectWith(deps, project, DESIGN_CHANGED_EVENT, data, component.slice(`/projects/${project.slug}`.length));
68
+ }
69
+ export { DESIGN_CHANGED_EVENT, announceDesignChangesWith };
70
+
71
+ //# sourceMappingURL=design-events.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-events.mjs","names":[],"sources":["../src/design-events.ts"],"sourcesContent":["/**\n * `design:changed`: a design moved after its baseline was approved, or no longer exists. It rides\n * the existing paths (signed webhooks and the notification fan-out) and is a normal subscribable\n * topic: it is not default-on (see `notify.ts`), so only people who opted in hear about it.\n *\n * Sent once per (project, design node, design version) from the first health check that sees the\n * change. The durable claim is `DesignNodeModel.claimChange`; with no confirmed public origin\n * nothing is sent and nothing is claimed, so the change is still announced once an origin exists.\n * There is no boot replay: an unannounced change waits for the next health check.\n */\nimport { emitWebhookEvent } from \"@storyshelf/core/adapter/webhook-events\";\nimport { designChange, type DesignChange, type DesignNodeModel } from \"@storyshelf/core/models\";\nimport type { DesignNode, Project } from \"@storyshelf/core/schema\";\nimport { createUrlBuilder } from \"@storyshelf/core/urls\";\nimport { credentialKeys } from \"./credential-keys.ts\";\nimport { clearPaused, notificationOrigin, warnPaused } from \"./notifications-pause.ts\";\nimport { notifyProjectWith, type NotifyDeps } from \"./notify.ts\";\n\n/** Event name of a design change. */\nexport const DESIGN_CHANGED_EVENT = \"design:changed\";\n\n/** What `design:changed` carries. */\nexport interface DesignChangedData extends Record<string, unknown> {\n projectId: string;\n /** Story file (the component) whose design changed. */\n componentPath: string;\n figmaUrl: string;\n change: DesignChange[\"change\"];\n designVersion: string | null;\n}\n\n/** One design a health check looked at. */\nexport interface DesignObservation {\n url: string;\n node: DesignNode | undefined;\n /** The component (story file) the design belongs to. */\n componentPath: string | null;\n /** Version of the baseline the component was approved at. */\n baselineVersion: string | null;\n}\n\n/**\n * Announce every observed design change not announced before. Never throws: a failure is logged\n * and the next health check tries again.\n */\nexport async function announceDesignChangesWith(\n deps: NotifyDeps,\n nodes: Pick<DesignNodeModel, \"claimChange\">,\n project: Pick<Project, \"id\" | \"slug\">,\n observations: readonly DesignObservation[],\n): Promise<void> {\n const changes = observations.flatMap((observation) => {\n const change = observation.componentPath\n ? designChange(observation.node, observation.baselineVersion)\n : null;\n return observation.node && observation.componentPath && change\n ? [\n {\n ...observation,\n node: observation.node,\n componentPath: observation.componentPath,\n change,\n },\n ]\n : [];\n });\n if (changes.length === 0 || !(await originConfirmed(deps))) return;\n await Promise.all(\n changes.map(async (item) => {\n try {\n if (await nodes.claimChange(item.node, item.change)) await announce(deps, project, item);\n } catch (error) {\n deps.logger.warn({ err: error, projectId: project.id }, \"design change not announced\");\n }\n }),\n );\n}\n\nasync function originConfirmed(deps: NotifyDeps): Promise<boolean> {\n const origin = await notificationOrigin(deps);\n if (origin === undefined) {\n warnPaused(deps.logger, DESIGN_CHANGED_EVENT);\n return false;\n }\n clearPaused(deps.logger);\n return true;\n}\n\nasync function announce(\n deps: NotifyDeps,\n project: Pick<Project, \"id\" | \"slug\">,\n item: { url: string; componentPath: string; change: DesignChange },\n): Promise<void> {\n const data: DesignChangedData = {\n projectId: project.id,\n componentPath: item.componentPath,\n figmaUrl: item.url,\n change: item.change.change,\n designVersion: item.change.designVersion,\n };\n await emitWebhookEvent(\n deps.db,\n { webhooks: deps.db.tables.webhooks },\n project.id,\n DESIGN_CHANGED_EVENT,\n data,\n credentialKeys(deps.config),\n deps.logger,\n );\n const component = createUrlBuilder(\"\").component(project.slug, item.componentPath);\n await notifyProjectWith(\n deps,\n project,\n DESIGN_CHANGED_EVENT,\n data,\n component.slice(`/projects/${project.slug}`.length),\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAmBA,MAAa,uBAAuB;;;;;AA0BpC,eAAsB,0BACpB,MACA,OACA,SACA,cACe;CACf,MAAM,UAAU,aAAa,SAAS,gBAAgB;EACpD,MAAM,SAAS,YAAY,gBACvB,aAAa,YAAY,MAAM,YAAY,eAAe,IAC1D;EACJ,OAAO,YAAY,QAAQ,YAAY,iBAAiB,SACpD,CACE;GACE,GAAG;GACH,MAAM,YAAY;GAClB,eAAe,YAAY;GAC3B;EACF,CACF,IACA,CAAC;CACP,CAAC;CACD,IAAI,QAAQ,WAAW,KAAK,CAAE,MAAM,gBAAgB,IAAI,GAAI;CAC5D,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,SAAS;EAC1B,IAAI;GACF,IAAI,MAAM,MAAM,YAAY,KAAK,MAAM,KAAK,MAAM,GAAG,MAAM,SAAS,MAAM,SAAS,IAAI;EACzF,SAAS,OAAO;GACd,KAAK,OAAO,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,6BAA6B;EACvF;CACF,CAAC,CACH;AACF;AAEA,eAAe,gBAAgB,MAAoC;CAEjE,IAAI,MADiB,mBAAmB,IAAI,MAC7B,KAAA,GAAW;EACxB,WAAW,KAAK,QAAQ,oBAAoB;EAC5C,OAAO;CACT;CACA,YAAY,KAAK,MAAM;CACvB,OAAO;AACT;AAEA,eAAe,SACb,MACA,SACA,MACe;CACf,MAAM,OAA0B;EAC9B,WAAW,QAAQ;EACnB,eAAe,KAAK;EACpB,UAAU,KAAK;EACf,QAAQ,KAAK,OAAO;EACpB,eAAe,KAAK,OAAO;CAC7B;CACA,MAAM,iBACJ,KAAK,IACL,EAAE,UAAU,KAAK,GAAG,OAAO,SAAS,GACpC,QAAQ,IACR,sBACA,MACA,eAAe,KAAK,MAAM,GAC1B,KAAK,MACP;CACA,MAAM,YAAY,iBAAiB,EAAE,CAAC,CAAC,UAAU,QAAQ,MAAM,KAAK,aAAa;CACjF,MAAM,kBACJ,MACA,SACA,sBACA,MACA,UAAU,MAAM,aAAa,QAAQ,OAAO,MAAM,CACpD;AACF"}
@@ -6,7 +6,7 @@ import { getStore } from "./store.mjs";
6
6
  import { notificationOrigin } from "./notifications-pause.mjs";
7
7
  import { buildStateFlags } from "./build-state-flags.mjs";
8
8
  import { createBuildStatePublisher, requestOpenBuildStates } from "@storyshelf/core/capture";
9
- //#region src/git-status.ts
9
+ // src/git-status.ts
10
10
  /** Ask for a build's state to be shown on its project's git channels (ADR 0014, decision 5). */
11
11
  /**
12
12
  * Show the build's current state (commit statuses and the pull-request comment) on every git
@@ -40,7 +40,6 @@ function inlinePublisher(store) {
40
40
  logger: store.logger
41
41
  } });
42
42
  }
43
- //#endregion
44
43
  export { requestBuildState, requestOpenBuildStatesNow };
45
44
 
46
45
  //# sourceMappingURL=git-status.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/hidden-data.ts
4
+ // src/hidden-data.ts
5
5
  /**
6
6
  * Snapshots stored in the database. With `testing` off they are hidden, not deleted (ADR 0006,
7
7
  * decision 1): the System page and the startup log say how many.
@@ -18,7 +18,6 @@ async function logHostingOnlyMode(db, logger) {
18
18
  }
19
19
  logger.info("testing is off: hosting Storybooks only (no capture, compare or baselines)");
20
20
  }
21
- //#endregion
22
21
  export { countHiddenSnapshots, logHostingOnlyMode };
23
22
 
24
23
  //# sourceMappingURL=hidden-data.mjs.map
package/dist/index.d.mts CHANGED
@@ -4,7 +4,6 @@ import { ShelfApp, ShelfContext, ShelfLifecycle, ShelfRouter } from "./app-types
4
4
  import { createAuthSystemHook } from "./notify.mjs";
5
5
  import { BrandTheme, NotificationsConfig, ShelfCompareOptions, ShelfConfig, ShelfNotificationsOptions, ShelfOptions, ShelfOptions as ShelfOptions$1, ShelfTestingOptions, UIConfig } from "@storyshelf/core/config";
6
6
  import { Logger, LoggerOptions, PinoTransport, createShelfLogger } from "@storyshelf/core/logger";
7
- //#region src/index.d.ts
8
7
  /**
9
8
  * Create the StoryShelf Hono app with all API routes and HTML pages.
10
9
  *
@@ -13,6 +12,5 @@ import { Logger, LoggerOptions, PinoTransport, createShelfLogger } from "@storys
13
12
  * fail-fast startup, or let the first request gate on settlement.
14
13
  */
15
14
  declare function createShelfApp(rawOptions: ShelfOptions$1): ShelfApp;
16
- //#endregion
17
15
  export { type BrandTheme, type Logger, type LoggerOptions, type NotificationsConfig, type PinoTransport, type ShelfApp, type ShelfCompareOptions, type ShelfConfig, type ShelfContext, type ShelfLifecycle, type ShelfNotificationsOptions, type ShelfOptions, type ShelfRouter, type ShelfTestingOptions, type UIConfig, createAuthSystemHook, createShelfApp, createShelfLogger };
18
16
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -52,7 +52,7 @@ import { STORYBOOK_TOKEN_PREFIX } from "@storyshelf/core/utils";
52
52
  import { createHttpMiddleware, createInstrumentedDatabase, createInstrumentedStorage } from "@storyshelf/observability";
53
53
  import { requestId } from "hono/request-id";
54
54
  import { createShelfLogger } from "@storyshelf/core/logger";
55
- //#region src/index.tsx
55
+ // src/index.tsx
56
56
  /**
57
57
  * StoryShelf app: compose database, storage, capture, auth, and notifier
58
58
  * adapters into a complete self-hosted visual-testing Hono app.
@@ -380,9 +380,8 @@ function registerDocs(app) {
380
380
  * from source (dev server, tests).
381
381
  */
382
382
  function packageVersion() {
383
- return "0.7.0";
383
+ return "0.9.0-next-d2cc082";
384
384
  }
385
- //#endregion
386
385
  export { createAuthSystemHook, createShelfApp, createShelfLogger };
387
386
 
388
387
  //# sourceMappingURL=index.mjs.map
@@ -5,7 +5,7 @@ import { notifySystemWith } from "../notify.mjs";
5
5
  import { failWith } from "./errors.mjs";
6
6
  import { AiBudgetAlertModel, AiUsageModel } from "@storyshelf/core/models";
7
7
  import { countedTokens, crossedThresholds, utcDay, utcDayStart } from "@storyshelf/core/insights";
8
- //#region src/insights/budget.ts
8
+ // src/insights/budget.ts
9
9
  /** DB-counted budget: pre-flight limits, usage rows and threshold alerts. */
10
10
  const HOUR_MS = 36e5;
11
11
  /** Tokens counted so far today (UTC), summed across all instances from rows. */
@@ -43,7 +43,6 @@ async function recordUsage(deps, input) {
43
43
  await fireAlerts(deps, crossedThresholds(before, after, dailyTokens), utcDay(now), after, dailyTokens);
44
44
  }
45
45
  }
46
- //#endregion
47
46
  export { assertWithinBudget, dayTokens, recordUsage };
48
47
 
49
48
  //# sourceMappingURL=budget.mjs.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { getStore } from "../store.mjs";
5
- //#region src/insights/deps.ts
5
+ // src/insights/deps.ts
6
6
  /** Snapshot the current request store into explicit deps (null when AI is off). */
7
7
  function insightDepsFromStore() {
8
8
  const store = getStore();
@@ -15,7 +15,6 @@ function insightDepsFromStore() {
15
15
  notify: store
16
16
  };
17
17
  }
18
- //#endregion
19
18
  export { insightDepsFromStore };
20
19
 
21
20
  //# sourceMappingURL=deps.mjs.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { HTTPException } from "hono/http-exception";
5
- //#region src/insights/errors.ts
5
+ // src/insights/errors.ts
6
6
  /** JSON errors for the insights API (`{ message }`, optional `Retry-After`). */
7
7
  /** Throw an HTTP error with a JSON `{ message }` body. */
8
8
  function failWith(status, message, retryAfterSeconds) {
@@ -16,7 +16,6 @@ function failWith(status, message, retryAfterSeconds) {
16
16
  })
17
17
  });
18
18
  }
19
- //#endregion
20
19
  export { failWith };
21
20
 
22
21
  //# sourceMappingURL=errors.mjs.map
@@ -34,7 +34,6 @@ async function loadHealthBadge(project) {
34
34
  score: scoreOf(toInsightView(row).output)
35
35
  };
36
36
  }
37
- //#endregion
38
37
  export { loadHealthBadge, loadHealthPanel };
39
38
 
40
39
  //# sourceMappingURL=health-panel.mjs.map
@@ -5,7 +5,7 @@ import { notifyProjectWith } from "../notify.mjs";
5
5
  import { recordUsage } from "./budget.mjs";
6
6
  import { InsightModel } from "@storyshelf/core/models";
7
7
  import { AiError } from "@storyshelf/core/ai";
8
- //#region src/insights/job.ts
8
+ // src/insights/job.ts
9
9
  /** Background insight job: summarize, record usage, persist the result, notify. */
10
10
  const running = /* @__PURE__ */ new Set();
11
11
  /** Wait for in-flight jobs (graceful teardown and tests). */
@@ -97,7 +97,6 @@ function spawnJob(deps, row, spec) {
97
97
  });
98
98
  running.add(promise);
99
99
  }
100
- //#endregion
101
100
  export { packResult, settleInsightJobs, spawnJob };
102
101
 
103
102
  //# sourceMappingURL=job.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { BuildModel, SnapshotModel } from "@storyshelf/core/models";
5
5
  import { buildHealthEvidence, resolveLimits, snapshotKey } from "@storyshelf/core/insights";
6
6
  import { modeSegment } from "@storyshelf/core/paths";
7
- //#region src/insights/load-health.ts
7
+ // src/insights/load-health.ts
8
8
  /** Load project-health evidence: build aggregates plus the most churny stories. */
9
9
  const DAY_MS = 864e5;
10
10
  /** Parse windows like `30d` (1–365 days); null for anything else. */
@@ -53,7 +53,6 @@ async function loadHealthEvidence(deps, project, window, days) {
53
53
  limits: resolveLimits(deps.ai.limits())
54
54
  });
55
55
  }
56
- //#endregion
57
56
  export { loadHealthEvidence, parseWindow };
58
57
 
59
58
  //# sourceMappingURL=load-health.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { CaptureAttemptModel, CaptureLogModel, CommentModel, SnapshotModel } from "@storyshelf/core/models";
5
5
  import { buildTriageEvidence, rankSnapshots, resolveLimits } from "@storyshelf/core/insights";
6
6
  import { modeSegment } from "@storyshelf/core/paths";
7
- //#region src/insights/load-triage.ts
7
+ // src/insights/load-triage.ts
8
8
  /** Load triage evidence inputs (snapshots, logs, comments, thumbnails) and assemble them. */
9
9
  function storyIdOf(log) {
10
10
  try {
@@ -92,7 +92,6 @@ async function loadTriageEvidence(deps, project, build) {
92
92
  limits
93
93
  });
94
94
  }
95
- //#endregion
96
95
  export { loadTriageEvidence };
97
96
 
98
97
  //# sourceMappingURL=load-triage.mjs.map
@@ -8,7 +8,7 @@ import { APPROVER_ROLES } from "../routers/builds.handlers.mjs";
8
8
  import { freshen } from "./stale.mjs";
9
9
  import { toInsightView } from "./view.mjs";
10
10
  import { InsightModel } from "@storyshelf/core/models";
11
- //#region src/insights/panel.ts
11
+ // src/insights/panel.ts
12
12
  /** Data for the build-review insight panel (null when AI is off for the project). */
13
13
  /** Load the panel for a build, or null when AI is off site-wide or for the project. */
14
14
  async function loadInsightPanel(project, build) {
@@ -22,7 +22,6 @@ async function loadInsightPanel(project, build) {
22
22
  canGenerate: role !== null && APPROVER_ROLES.includes(role)
23
23
  };
24
24
  }
25
- //#endregion
26
25
  export { loadInsightPanel };
27
26
 
28
27
  //# sourceMappingURL=panel.mjs.map
@@ -8,7 +8,7 @@ import { loadTriageEvidence } from "./load-triage.mjs";
8
8
  import { InsightModel } from "@storyshelf/core/models";
9
9
  import { HEALTH_SYSTEM, PROMPT_VERSION, TRIAGE_SYSTEM, computeInputHash, healthEnvelopeSchema, triageEnvelopeSchema } from "@storyshelf/core/insights";
10
10
  import { createHash } from "node:crypto";
11
- //#region src/insights/request.ts
11
+ // src/insights/request.ts
12
12
  /** Request-side insight orchestration: evidence, hash, cache check, budget, spawn. */
13
13
  /** The profile a project uses: override, else its gate value (`default` = default profile). */
14
14
  function profileFor(deps, project, override) {
@@ -107,7 +107,6 @@ async function requestHealth(deps, project, window, options) {
107
107
  });
108
108
  });
109
109
  }
110
- //#endregion
111
110
  export { profileFor, requestHealth, requestTriage };
112
111
 
113
112
  //# sourceMappingURL=request.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { InsightModel } from "@storyshelf/core/models";
5
5
  import { STALE_RUN_MS } from "@storyshelf/core/retention";
6
- //#region src/insights/stale.ts
6
+ // src/insights/stale.ts
7
7
  /** Lazy interruption check: a run stuck past the stale window is failed on read. */
8
8
  /** Return the row, first marking it `interrupted` when it is stale and still in flight. */
9
9
  async function freshen(deps, row) {
@@ -15,7 +15,6 @@ async function freshen(deps, row) {
15
15
  errorCode: "interrupted"
16
16
  };
17
17
  }
18
- //#endregion
19
18
  export { freshen };
20
19
 
21
20
  //# sourceMappingURL=stale.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { AiUsageModel } from "@storyshelf/core/models";
5
5
  import { countedTokens, utcDay } from "@storyshelf/core/insights";
6
- //#region src/insights/usage-report.ts
6
+ // src/insights/usage-report.ts
7
7
  /** Aggregates for the site-admin AI usage page (counted tokens per day and profile). */
8
8
  const DAY_MS = 864e5;
9
9
  function addTo(map, key, make, tokens, failed) {
@@ -54,7 +54,6 @@ async function buildUsageReport(deps, windowDays = 14, now = /* @__PURE__ */ new
54
54
  dailyTokens: dailyTokens ?? null
55
55
  };
56
56
  }
57
- //#endregion
58
57
  export { buildUsageReport };
59
58
 
60
59
  //# sourceMappingURL=usage-report.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/insights/view.ts
4
+ // src/insights/view.ts
5
5
  function parseResult(raw) {
6
6
  if (!raw) return {
7
7
  output: null,
@@ -42,7 +42,6 @@ function toInsightView(row) {
42
42
  finishedAt: row.finishedAt
43
43
  };
44
44
  }
45
- //#endregion
46
45
  export { toInsightView };
47
46
 
48
47
  //# sourceMappingURL=view.mjs.map
@@ -1,14 +1,13 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/job-canceller.ts
4
+ // src/job-canceller.ts
5
5
  /** Ask each queue that can cancel to cancel the build's jobs; a queue without `cancel` is skipped. */
6
6
  function createJobCanceller(queues) {
7
7
  return async (buildId) => {
8
8
  return (await Promise.all(queues.map(async (queue) => await queue?.cancel?.(buildId) ?? false))).some(Boolean);
9
9
  };
10
10
  }
11
- //#endregion
12
11
  export { createJobCanceller };
13
12
 
14
13
  //# sourceMappingURL=job-canceller.mjs.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { DATABASE_QUEUE_METADATA, createDatabaseCaptureQueue } from "@storyshelf/core/capture";
5
- //#region src/job-queue.ts
5
+ // src/job-queue.ts
6
6
  /**
7
7
  * Create the lazy queue polling `kinds`, with `retries` after a first failed attempt, the lease
8
8
  * of `testing.leaseSeconds` and the clock of `testing.queueClock` (production: real time).
@@ -45,7 +45,6 @@ function queueView(get) {
45
45
  cancel: async (id) => await get().cancel(id)
46
46
  };
47
47
  }
48
- //#endregion
49
48
  export { createJobQueue };
50
49
 
51
50
  //# sourceMappingURL=job-queue.mjs.map