cursedbelt 4.1.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/react/components/Autocomplete.d.ts.map +1 -1
  2. package/dist/react/components/Autocomplete.js +1 -1
  3. package/dist/react/components/Autocomplete.js.map +1 -1
  4. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  5. package/dist/react/components/ComboboxField.js +1 -1
  6. package/dist/react/components/ComboboxField.js.map +1 -1
  7. package/dist/react/media/CanvasVideoPlayer.d.ts +3 -2
  8. package/dist/react/media/CanvasVideoPlayer.d.ts.map +1 -1
  9. package/dist/react/media/CanvasVideoPlayer.js +4 -3
  10. package/dist/react/media/CanvasVideoPlayer.js.map +1 -1
  11. package/dist/react/media/FrameGrabber.d.ts +16 -2
  12. package/dist/react/media/FrameGrabber.d.ts.map +1 -1
  13. package/dist/react/media/FrameGrabber.js +68 -43
  14. package/dist/react/media/FrameGrabber.js.map +1 -1
  15. package/dist/react/media/PictureEditor.d.ts +17 -2
  16. package/dist/react/media/PictureEditor.d.ts.map +1 -1
  17. package/dist/react/media/PictureEditor.js +33 -7
  18. package/dist/react/media/PictureEditor.js.map +1 -1
  19. package/dist/react/media/VideoChapterEditor.d.ts +17 -2
  20. package/dist/react/media/VideoChapterEditor.d.ts.map +1 -1
  21. package/dist/react/media/VideoChapterEditor.js +21 -3
  22. package/dist/react/media/VideoChapterEditor.js.map +1 -1
  23. package/dist/react/media/VideoCutEditor.d.ts +16 -2
  24. package/dist/react/media/VideoCutEditor.d.ts.map +1 -1
  25. package/dist/react/media/VideoCutEditor.js +21 -3
  26. package/dist/react/media/VideoCutEditor.js.map +1 -1
  27. package/dist/react/media/VideoPlayer.d.ts +37 -9
  28. package/dist/react/media/VideoPlayer.d.ts.map +1 -1
  29. package/dist/react/media/VideoPlayer.js +130 -39
  30. package/dist/react/media/VideoPlayer.js.map +1 -1
  31. package/dist/react/media/hlsSource.d.ts +24 -3
  32. package/dist/react/media/hlsSource.d.ts.map +1 -1
  33. package/dist/react/media/hlsSource.js +109 -8
  34. package/dist/react/media/hlsSource.js.map +1 -1
  35. package/dist/react/media/pictureEditor.css +2 -0
  36. package/dist/react/media/sourceFault.d.ts +146 -0
  37. package/dist/react/media/sourceFault.d.ts.map +1 -0
  38. package/dist/react/media/sourceFault.js +139 -0
  39. package/dist/react/media/sourceFault.js.map +1 -0
  40. package/dist/react/media/videoChapterEditor.css +19 -0
  41. package/dist/react/media/videoCutEditor.css +22 -0
  42. package/dist/react/media-gallery/MediaGallery.d.ts +21 -3
  43. package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
  44. package/dist/react/media-gallery/MediaGallery.js +178 -17
  45. package/dist/react/media-gallery/MediaGallery.js.map +1 -1
  46. package/dist/react/media-gallery/galleryItemMedia.d.ts +4 -0
  47. package/dist/react/media-gallery/galleryItemMedia.d.ts.map +1 -1
  48. package/dist/react/media-gallery/galleryItemMedia.js +27 -3
  49. package/dist/react/media-gallery/galleryItemMedia.js.map +1 -1
  50. package/dist/react/media-gallery/mediaGalleryModel.d.ts.map +1 -1
  51. package/dist/react/media-gallery/mediaGalleryModel.js +5 -0
  52. package/dist/react/media-gallery/mediaGalleryModel.js.map +1 -1
  53. package/dist/react/media-gallery/types.d.ts +23 -0
  54. package/dist/react/media-gallery/types.d.ts.map +1 -1
  55. package/dist/scripts/guardrailsEnforce.d.ts +1 -0
  56. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  57. package/dist/styles-areas/analytics.css +1 -1
  58. package/dist/styles-areas/data-table.css +1 -1
  59. package/dist/styles-areas/fields.css +1 -1
  60. package/dist/styles-areas/media-gallery.css +1 -1
  61. package/dist/styles-areas/media.css +1 -1
  62. package/dist/styles-areas/wizard.css +1 -1
  63. package/package.json +51 -6
  64. package/scripts/demoServer.ts +211 -0
  65. package/scripts/gate.ts +101 -0
  66. package/scripts/guardrailsEnforce.spec.ts +313 -1
  67. package/scripts/guardrailsEnforce.ts +283 -26
  68. package/scripts/paths.ts +1 -1
  69. package/src/demoFixture.spec.ts +54 -10
  70. package/src/demoStaticServer.spec.ts +169 -0
  71. package/src/publishShape.spec.ts +79 -0
  72. package/src/react/components/Autocomplete.tsx +11 -1
  73. package/src/react/components/ComboboxField.spec.tsx +12 -0
  74. package/src/react/components/ComboboxField.tsx +11 -1
  75. package/src/react/media/CanvasVideoPlayer.tsx +11 -6
  76. package/src/react/media/FrameGrabber.spec.tsx +57 -1
  77. package/src/react/media/FrameGrabber.tsx +138 -84
  78. package/src/react/media/PictureEditor.spec.tsx +90 -0
  79. package/src/react/media/PictureEditor.tsx +78 -23
  80. package/src/react/media/VideoChapterEditor.spec.tsx +86 -0
  81. package/src/react/media/VideoChapterEditor.tsx +64 -18
  82. package/src/react/media/VideoCutEditor.spec.tsx +44 -0
  83. package/src/react/media/VideoCutEditor.tsx +63 -18
  84. package/src/react/media/VideoPlayer.spec.tsx +101 -0
  85. package/src/react/media/VideoPlayer.tsx +221 -73
  86. package/src/react/media/hlsSource.answer.spec.ts +255 -0
  87. package/src/react/media/hlsSource.ts +136 -8
  88. package/src/react/media/pictureEditor.css +2 -0
  89. package/src/react/media/sourceFault.spec.tsx +224 -0
  90. package/src/react/media/sourceFault.tsx +220 -0
  91. package/src/react/media/videoChapterEditor.css +19 -0
  92. package/src/react/media/videoCutEditor.css +22 -0
  93. package/src/react/media-gallery/MediaGallery.spec.tsx +311 -0
  94. package/src/react/media-gallery/MediaGallery.tsx +382 -54
  95. package/src/react/media-gallery/galleryItemMedia.tsx +27 -4
  96. package/src/react/media-gallery/mediaGalleryModel.spec.ts +36 -0
  97. package/src/react/media-gallery/mediaGalleryModel.ts +4 -0
  98. package/src/react/media-gallery/types.ts +23 -0
  99. package/src/styles-areas/analytics.css +1 -1
  100. package/src/styles-areas/data-table.css +1 -1
  101. package/src/styles-areas/fields.css +1 -1
  102. package/src/styles-areas/media-gallery.css +1 -1
  103. package/src/styles-areas/media.css +1 -1
  104. package/src/styles-areas/wizard.css +1 -1
  105. package/src/testFilesRunInParallel.spec.ts +3 -3
  106. package/src/typecheckCachesAreSeparate.spec.ts +2 -2
  107. package/src/verifyGraph.spec.ts +75 -108
  108. package/scripts/verify.ts +0 -296
@@ -9,17 +9,40 @@ import { jsx as _jsx } from "react/jsx-runtime";
9
9
  * signed-URL app is a request per row per toggle. A module both import is the only shape
10
10
  * that cannot drift; re-implementing either inside the table is what this file prevents.
11
11
  */
12
- import { useEffect, useState } from 'react';
12
+ import { useCallback, useEffect, useRef, useState } from 'react';
13
13
  import { staticItemMedia } from './mediaGalleryModel';
14
14
  /**
15
15
  * The item's resolved media: static URL fields immediately, `resolveMedia` results merged
16
16
  * in when the item needs them (cached per id for the gallery's lifetime).
17
+ *
18
+ * `refresh` throws the cached answer away and asks the app again — see its own note; it is
19
+ * what makes a `403` from a stale signed URL recoverable instead of a sentence on screen.
17
20
  */
18
21
  export function useItemMedia(item, cache) {
19
22
  const staticMedia = staticItemMedia(item);
20
23
  const needsResolve = Boolean(item.resolveMedia) && !item.url;
21
24
  const [resolved, setResolved] = useState(null);
22
25
  const [resolving, setResolving] = useState(needsResolve);
26
+ /** Bumped by {@link refresh} so the effect below re-runs against an emptied cache. */
27
+ const [attempt, setAttempt] = useState(0);
28
+ /**
29
+ * 🔴 ONE re-ask per item, for the life of this mount.
30
+ *
31
+ * The whole reason to re-ask is a signed URL that went stale, and the app's answer to that
32
+ * is a fresh token — so if the second URL fails the same way, asking a third time is an
33
+ * unbounded loop against something that is not going to change, which is the same spinner
34
+ * this batch removed with more requests in it. `RECOVERY_BUDGET` in `hlsSource.ts` bounds
35
+ * its retries for exactly this reason; this is that rule one layer up.
36
+ */
37
+ const reAsked = useRef(new Set());
38
+ const refresh = useCallback(() => {
39
+ if (!needsResolve || reAsked.current.has(item.id))
40
+ return false;
41
+ reAsked.current.add(item.id);
42
+ cache.current.delete(item.id);
43
+ setAttempt((n) => n + 1);
44
+ return true;
45
+ }, [item.id, needsResolve, cache]);
23
46
  useEffect(() => {
24
47
  if (!needsResolve)
25
48
  return;
@@ -46,8 +69,9 @@ export function useItemMedia(item, cache) {
46
69
  return () => {
47
70
  live = false;
48
71
  };
49
- }, [item.id, needsResolve, cache, item.resolveMedia]);
50
- return { media: { ...(resolved ?? {}), ...staticMedia }, resolving };
72
+ // `attempt` is the re-ask: it is not read in the body, it is what re-runs it.
73
+ }, [item.id, needsResolve, cache, item.resolveMedia, attempt]);
74
+ return { media: { ...(resolved ?? {}), ...staticMedia }, resolving, refresh };
51
75
  }
52
76
  /**
53
77
  * "13 Aug 2026" — the created date in the shortest form that stays unambiguous.
@@ -1 +1 @@
1
- {"version":3,"file":"galleryItemMedia.js","sourceRoot":"","sources":["../../../src/react/media-gallery/galleryItemMedia.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"galleryItemMedia.js","sourceRoot":"","sources":["../../../src/react/media-gallery/galleryItemMedia.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mediaGalleryModel.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/mediaGalleryModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAK1F,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAExE;AAED,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAa3D,CAAC;AAkBF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EAAE,GACxB;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAO1C;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAI/D;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAazE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EAAE,EACzB,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,aAAa,GAClC,gBAAgB,EAAE,CAYpB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE;IAClC,GAAG,EAAE,iBAAiB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,EAoBA,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,gBAAgB,EAAE,EACzB,KAAK,EAAE,iBAAiB,GACvB,gBAAgB,EAAE,CAyBpB;AAED,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,qBAAqB,CAW7E;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE7D;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAIjF"}
1
+ {"version":3,"file":"mediaGalleryModel.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/mediaGalleryModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAK1F,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAExE;AAED,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAa3D,CAAC;AAkBF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EAAE,GACxB;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAO1C;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAI/D;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAazE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EAAE,EACzB,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,aAAa,GAClC,gBAAgB,EAAE,CAYpB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE;IAClC,GAAG,EAAE,iBAAiB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,EAoBA,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,gBAAgB,EAAE,EACzB,KAAK,EAAE,iBAAiB,GACvB,gBAAgB,EAAE,CAyBpB;AAED,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,qBAAqB,CAe7E;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE7D;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAIjF"}
@@ -183,6 +183,11 @@ export function staticItemMedia(item) {
183
183
  // Additional to `streamUrl`, never instead of it — see `MediaGalleryItemMedia.hlsUrl`.
184
184
  if (item.hlsUrl)
185
185
  media.hlsUrl = item.hlsUrl;
186
+ // "We could not ASK about the ladder", which is not the same as not having one — see
187
+ // `MediaGalleryItemMedia.playbackDegraded`. Forwarded only when true, so the ordinary
188
+ // ladder-less video carries nothing and the stage has nothing to say about it.
189
+ if (item.playbackDegraded)
190
+ media.playbackDegraded = true;
186
191
  if (item.vttUrl)
187
192
  media.vttUrl = item.vttUrl;
188
193
  if (item.processingStatus)
@@ -1 +1 @@
1
- {"version":3,"file":"mediaGalleryModel.js","sourceRoot":"","sources":["../../../src/react/media-gallery/mediaGalleryModel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mediaGalleryModel.js","sourceRoot":"","sources":["../../../src/react/media-gallery/mediaGalleryModel.ts"],"names":[],"mappings":"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"}
@@ -47,6 +47,29 @@ export interface MediaGalleryItemMedia {
47
47
  * and `preferBundledHls`, which decides where the engine comes from.
48
48
  */
49
49
  hlsUrl?: string;
50
+ /**
51
+ * The ladder was not ASKED ABOUT successfully — so this play is the progressive fallback and
52
+ * the app knows it, rather than merely having no ladder.
53
+ *
54
+ * 🔴 It is NOT "there is no ladder". A video whose ladder has simply never been built is the
55
+ * ordinary case and stays quiet: {@link hlsUrl} is absent, `streamUrl` plays, nothing is
56
+ * wrong. This flag is the other thing — the app's probe of its own media store did not
57
+ * answer, so it cannot tell a ladder that is missing from one it could not reach, and it has
58
+ * served the progressive copy on that ignorance.
59
+ *
60
+ * 🔴 And it is NOT {@link processingStatus} `'failed'`. That badge says the optimization
61
+ * failed; here the optimization may well have succeeded and we could not ask. Different
62
+ * cause, different fix, different lifetime — this one usually clears on the next open — so
63
+ * the player draws a SECOND badge rather than borrowing that one's sentence.
64
+ *
65
+ * Worth a badge because the fallback is expensive and silent: in `apps/collections` the
66
+ * progressive `.web.mp4` averages 467 MB and reaches 4.4 GB, which is past what Cloudflare
67
+ * will cache (`x-bs-edge-cache: MISS-TOO-LARGE`), so every play and every seek is pulled off
68
+ * the owner's own Mac; a ladder segment is ~1 MB and comes from the edge. For eight days
69
+ * nothing in the fleet could say which of the two it was serving, and the owner found out by
70
+ * watching a video stall.
71
+ */
72
+ playbackDegraded?: boolean;
50
73
  /**
51
74
  * WebVTT scrub-preview track — the sprite-sheet index that puts real frame thumbnails on
52
75
  * the scrub bar instead of a bare timecode. Passed straight to the player's `thumbnails`.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,CAAC;AAEf;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACzE;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;CAC5D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,CAAC;AAEf;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACzE;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;CAC5D"}
@@ -26,4 +26,5 @@ export declare function parseFileAllows(source: string): {
26
26
  warnings: string[];
27
27
  };
28
28
  export type { Rule, Violation };
29
+ export declare function beltExportedComponentNames(reactRoot?: string): string[];
29
30
  //# sourceMappingURL=guardrailsEnforce.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AAwKA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AAu2BD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AAweD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAkBtC,CAAC;AASF,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AA0LA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AA+4BD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AAweD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAkBtC,CAAC;AASF,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAmGhC,wBAAgB,0BAA0B,CAAC,SAAS,GAAE,MAAwB,GAAG,MAAM,EAAE,CAyBxF"}
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1309 candidate(s) scanned.
18
+ * when this file is stale. 1312 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1345 candidate(s) scanned.
18
+ * when this file is stale. 1347 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 610 candidate(s) scanned.
18
+ * when this file is stale. 613 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2014 candidate(s) scanned.
18
+ * when this file is stale. 2115 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2734 candidate(s) scanned.
18
+ * when this file is stale. 2825 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 386 candidate(s) scanned.
18
+ * when this file is stale. 389 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "4.1.1",
3
+ "version": "4.4.0",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
@@ -31,10 +31,10 @@
31
31
  "styles": "bun run styles:static && bun run styles:utilities && bun run styles:areas",
32
32
  "styles:static": "bun run scripts/generateStaticStyles.ts",
33
33
  "styles:utilities": "bun run scripts/generateUtilityStyles.ts",
34
- "test": "NODE_ENV=development bun test src --parallel=6",
34
+ "test": "NODE_ENV=development bun test src scripts --timeout 60000 --parallel=6",
35
35
  "demo": "vite --config demo/vite.config.ts",
36
36
  "demo:build": "vite build --config demo/vite.config.ts",
37
- "demo:serve": "bun run demo:build && vite preview --config demo/vite.config.ts",
37
+ "demo:serve": "bun run demo:build && bun run scripts/demoServer.ts",
38
38
  "build": "rm -rf dist.next dist.prev && bun run scripts/generateStaticStyles.ts && bun run scripts/generateUtilityStyles.ts && bun run scripts/generateAreaStyles.ts && tsc --project tsconfig.build.json --outDir dist.next && tsc --project tsconfig.scripts.build.json --outDir dist.next/scripts && CURSEDBELT_DIST_DIR=dist.next bun run scripts/copyDistAssets.ts && CURSEDBELT_DIST_DIR=dist.next bun run scripts/checkDistExports.ts &&{ [ -d dist ] && mv dist dist.prev || true; } && mv dist.next dist && rm -rf dist.prev",
39
39
  "e2e": "playwright test --config e2e/playwright.config.ts",
40
40
  "e2e:filter-rail": "playwright test --config e2e/playwright.config.ts filter-rail.spec.ts",
@@ -42,13 +42,15 @@
42
42
  "e2e:stage-layout": "playwright test --config e2e/playwright.config.ts stage-layout.spec.ts",
43
43
  "e2e:dialog-reach": "playwright test --config e2e/playwright.config.ts dialog-reach.spec.ts",
44
44
  "e2e:video-turn": "playwright test --config e2e/playwright.config.ts video-turn.spec.ts",
45
+ "e2e:playback-degraded": "playwright test --config e2e/playwright.config.ts playback-degraded.spec.ts",
45
46
  "e2e:resize-grip": "playwright test --config e2e/playwright.config.ts resize-grip-rail.spec.ts",
46
47
  "e2e:touch": "playwright test --config e2e/playwright.config.ts --project=touch",
47
48
  "done:serial": "bun run typecheck && bun run lint && bun run test && bun run build",
48
49
  "paths": "bun run scripts/paths.ts",
49
- "verify": "bun run scripts/verify.ts",
50
- "prepublishOnly": "bun run verify",
51
- "styles:areas": "bun run scripts/generateAreaStyles.ts"
50
+ "verify": "bun run gate",
51
+ "prepublishOnly": "bun run gate --force",
52
+ "styles:areas": "bun run scripts/generateAreaStyles.ts",
53
+ "gate": "bun run scripts/gate.ts"
52
54
  },
53
55
  "exports": {
54
56
  ".": {
@@ -686,5 +688,48 @@
686
688
  "repository": {
687
689
  "type": "git",
688
690
  "url": "git+https://github.com/curtwphillips/cursedbelt.git"
691
+ },
692
+ "gate": {
693
+ "stages": [
694
+ {
695
+ "script": "paths"
696
+ },
697
+ {
698
+ "script": "typecheck:root"
699
+ },
700
+ {
701
+ "script": "typecheck:specs"
702
+ },
703
+ {
704
+ "script": "typecheck:scripts"
705
+ },
706
+ {
707
+ "script": "demo:check"
708
+ },
709
+ {
710
+ "script": "styles"
711
+ },
712
+ {
713
+ "script": "build",
714
+ "needs": [
715
+ "styles"
716
+ ],
717
+ "why": "its first two steps are the same generators; two writers on one stylesheet is a race"
718
+ },
719
+ {
720
+ "script": "test",
721
+ "needs": [
722
+ "styles"
723
+ ],
724
+ "why": "stylesStaticMatches / stylesUtilitiesMatches read those two files and assert they are current"
725
+ },
726
+ {
727
+ "script": "e2e",
728
+ "needs": [
729
+ "styles"
730
+ ],
731
+ "why": "the demo bundle it drives is compiled from the same stylesheets"
732
+ }
733
+ ]
689
734
  }
690
735
  }
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * The static server `bun run e2e` drives — the built demo, served by code this repo owns.
4
+ *
5
+ * ## Why this exists instead of `vite preview`
6
+ *
7
+ * Measured 2026-09-18 (task 388): `bun run verify` went red about one run in four on an
8
+ * unmodified tree, always the same way — `e2e` failing at exactly `webServer.timeout`
9
+ * (120.1s) with all 138 specs marked failed, and the real cause 150 lines below the noise:
10
+ *
11
+ * [WebServer] error: write after end
12
+ * [WebServer] code: "ERR_STREAM_WRITE_AFTER_END"
13
+ * [WebServer] at advanceResponsePipeline (node:_http_server:1343:38)
14
+ * [WebServer] error: script "demo:serve" exited with code 1
15
+ *
16
+ * That throw comes out of Bun 1.4.2's `node:http` compatibility layer, *after* the connect
17
+ * handler `vite preview` installed has returned — so no middleware, and no `server.on`
18
+ * listener on the connect app, is positioned to catch it. It fires when the peer closes a
19
+ * socket the response is still being written to, which is the normal state of affairs with
20
+ * eight Playwright workers: every navigation supersedes its own in-flight subresource
21
+ * requests, and `page.goto` during teardown abandons whatever was in flight.
22
+ *
23
+ * `Bun.serve` is a different layer. A handler returns a `Response`; a peer that hangs up
24
+ * cancels the body stream, and there is no socket write for user code to get wrong. The
25
+ * `error` hook below is the only place a fault can surface, and it answers with a 500
26
+ * instead of exiting.
27
+ *
28
+ * 🔴 This is deliberately the dumbest static server that can serve the fixture, because
29
+ * every feature it does not have is a way it cannot die halfway through a gate. No
30
+ * compression, no range requests, no directory listing, no watch mode, no HMR. `bun run
31
+ * demo` is still vite's dev server — a human editing a primitive wants the HMR, and that
32
+ * process has one tab attached to it rather than eight aborting workers.
33
+ */
34
+ import { statSync } from 'node:fs';
35
+ import { extname, resolve, sep } from 'node:path';
36
+ import { DEMO_DIST_DIR, DEMO_HOST, DEMO_PORT, DEMO_URL } from '../demo/devServer';
37
+
38
+ /**
39
+ * 🔴 Never cached, by anything. The gate's whole claim is that it tested the bytes in the
40
+ * tree; a 304 from a browser profile that outlived the build would quietly break that, and
41
+ * it would break it in the direction that reads green.
42
+ */
43
+ const NO_STORE = { 'cache-control': 'no-store, max-age=0' } as const;
44
+
45
+ /**
46
+ * The request path a URL resolves to inside `root`, or `null` for anything that is not a
47
+ * file under it.
48
+ *
49
+ * Pure and exported so the traversal refusal is provable without a socket.
50
+ */
51
+ export function resolveRequestPath(root: string, pathname: string): string | null {
52
+ let decoded: string;
53
+ try {
54
+ decoded = decodeURIComponent(pathname);
55
+ } catch {
56
+ // A malformed `%` escape. Not a path, and not worth guessing at.
57
+ return null;
58
+ }
59
+ if (decoded.includes('\0')) return null;
60
+ const wanted = decoded === '' || decoded === '/' ? '/index.html' : decoded;
61
+ // `resolve` collapses `..` itself; the prefix check below is what makes that a
62
+ // guarantee rather than a belief about how many segments the caller sent.
63
+ const candidates = [resolve(root, `.${wanted}`)];
64
+ // The fixture pages are a multi-page BUILD, so `/table-layout` and `/table-layout.html`
65
+ // are the same page. vite preview resolved both; specs use the explicit form, and a
66
+ // silent 404 on the bare one would be a difference nobody would notice until it bit.
67
+ if (extname(wanted) === '') candidates.push(resolve(root, `.${wanted}.html`));
68
+
69
+ const fence = root.endsWith(sep) ? root : root + sep;
70
+ for (const candidate of candidates) {
71
+ if (candidate !== root && !candidate.startsWith(fence)) continue;
72
+ try {
73
+ if (statSync(candidate).isFile()) return candidate;
74
+ } catch {
75
+ // Missing, or a directory we will not list. Try the next shape.
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+
81
+ /**
82
+ * Faults that are the PEER's doing, not ours: a client that went away mid-response.
83
+ *
84
+ * 🔴 The allow-list is closed on purpose. A blanket `uncaughtException` handler on a test
85
+ * fixture is how a server keeps serving after it has lost the thing it was serving, and
86
+ * the gate then measures a corpse that answers 200. Anything not named here still kills
87
+ * the process, loudly, which is the behaviour every other fault should have.
88
+ */
89
+ const PEER_HANGUP_CODES: ReadonlySet<string> = new Set([
90
+ 'ECONNRESET',
91
+ 'ECONNABORTED',
92
+ 'EPIPE',
93
+ 'ERR_STREAM_WRITE_AFTER_END',
94
+ 'ERR_STREAM_DESTROYED',
95
+ 'ERR_STREAM_PREMATURE_CLOSE',
96
+ 'ABORT_ERR',
97
+ ]);
98
+
99
+ /** Whether a thrown value is a peer hang-up rather than a fault in this server. */
100
+ export function isPeerHangup(thrown: unknown): boolean {
101
+ if (typeof thrown !== 'object' || thrown === null) return false;
102
+ const code = (thrown as { code?: unknown }).code;
103
+ if (typeof code === 'string' && PEER_HANGUP_CODES.has(code)) return true;
104
+ const name = (thrown as { name?: unknown }).name;
105
+ return name === 'AbortError';
106
+ }
107
+
108
+ export interface DemoServerOptions {
109
+ /** The directory to serve. Defaults to the built demo. */
110
+ root?: string;
111
+ /** Defaults to `DEMO_PORT`; `0` takes an ephemeral one, which is what the spec uses. */
112
+ port?: number;
113
+ hostname?: string;
114
+ }
115
+
116
+ export function startDemoServer(options: DemoServerOptions = {}): Bun.Server<undefined> {
117
+ const root = options.root ?? DEMO_DIST_DIR;
118
+ return Bun.serve({
119
+ port: options.port ?? DEMO_PORT,
120
+ // 🔴 One literal address, never the name — `demo/devServer.ts` has the measurement.
121
+ // Binding `localhost` let two processes hold 4318 at once, on `::1` and `127.0.0.1`,
122
+ // with no collision between them.
123
+ hostname: options.hostname ?? DEMO_HOST,
124
+ // 🔴 EXPLICIT, and the single least obvious line in this file. Bun.serve defaults to
125
+ // SO_REUSEPORT: measured 2026-09-18 on Bun 1.4.2, a second process binding a port
126
+ // another one already holds SUCCEEDS, prints a ready line, and serves nothing —
127
+ // every request is still answered by the first. That is `strictPort: false` with the
128
+ // failure hidden one layer deeper, and it would have made this whole change worse
129
+ // than what it replaced: the gate would build the demo, "serve" it, and then test
130
+ // whatever stale bundle a stray `bun run demo` was holding. With this, the bind
131
+ // throws EADDRINUSE and `main()` says so in one line.
132
+ reusePort: false,
133
+ development: false,
134
+ // Long enough for the heaviest chunk on a loaded machine; short enough that a
135
+ // wedged connection cannot hold a gate open. Bun's default is 10s.
136
+ idleTimeout: 60,
137
+ fetch(request) {
138
+ const file = resolveRequestPath(root, new URL(request.url).pathname);
139
+ if (!file) return new Response('not found\n', { status: 404, headers: NO_STORE });
140
+ return new Response(Bun.file(file), { headers: NO_STORE });
141
+ },
142
+ error(thrown) {
143
+ // The one seam a fault can reach. Returning a Response keeps the process alive;
144
+ // this is the hook `vite preview` had no equivalent of.
145
+ if (!isPeerHangup(thrown)) {
146
+ process.stderr.write(`demo server: request failed — ${thrown instanceof Error ? thrown.stack : String(thrown)}\n`);
147
+ }
148
+ return new Response('demo server error\n', { status: 500, headers: NO_STORE });
149
+ },
150
+ });
151
+ }
152
+
153
+ /**
154
+ * 🔴 Both halves matter. Exiting non-zero the moment the bundle or the port is wrong is
155
+ * what turns "Playwright waited 120s and then failed 138 specs" into one line a reader
156
+ * believes — and `$FORGE/tools/gate.ts` lifts these exact words to the top of a red gate.
157
+ */
158
+ async function main(): Promise<void> {
159
+ try {
160
+ if (!statSync(DEMO_DIST_DIR).isDirectory()) throw new Error('not a directory');
161
+ } catch {
162
+ process.stderr.write(
163
+ `demo server: no built demo at ${DEMO_DIST_DIR} — run \`bun run demo:build\` first.\n` +
164
+ '`bun run demo:serve` does both, and that is what the e2e webServer runs.\n',
165
+ );
166
+ process.exit(1);
167
+ }
168
+
169
+ let server: Bun.Server<undefined>;
170
+ try {
171
+ server = startDemoServer();
172
+ } catch (thrown) {
173
+ const code = (thrown as { code?: string } | null)?.code;
174
+ if (code === 'EADDRINUSE') {
175
+ process.stderr.write(
176
+ `demo server: EADDRINUSE — port ${DEMO_PORT} is already taken, so the gate cannot serve ` +
177
+ 'the demo it just built.\nSomething else is listening (a stray `bun run demo`, or a ' +
178
+ 'previous run that outlived its Playwright). Stop it and run the gate again.\n',
179
+ );
180
+ process.exit(1);
181
+ }
182
+ throw thrown;
183
+ }
184
+
185
+ // 🔴 Ask ourselves, over the socket, on the URL the specs are pointed at — before
186
+ // Playwright starts a 120-second wait it cannot explain. This catches the shapes a
187
+ // successful `bind` does not: a `localhost` that resolved to an address the client will
188
+ // not use, and a `dist` that built but emitted no `index.html`.
189
+ try {
190
+ const probe = await fetch(DEMO_URL, { signal: AbortSignal.timeout(5_000) });
191
+ if (!probe.ok) throw new Error(`${DEMO_URL} answered ${probe.status}`);
192
+ } catch (thrown) {
193
+ process.stderr.write(
194
+ `demo server: bound ${DEMO_PORT}, but ${DEMO_URL} does not answer — ` +
195
+ `${thrown instanceof Error ? thrown.message : String(thrown)}\n` +
196
+ `Nothing can drive this. Check that \`bun run demo:build\` wrote ${DEMO_DIST_DIR}/index.html.\n`,
197
+ );
198
+ await server.stop(true);
199
+ process.exit(1);
200
+ }
201
+
202
+ for (const signal of ['SIGINT', 'SIGTERM'] as const) {
203
+ process.on(signal, () => {
204
+ void server.stop(true);
205
+ process.exit(0);
206
+ });
207
+ }
208
+ process.stdout.write(`demo server: serving ${DEMO_DIST_DIR} at ${DEMO_URL}\n`);
209
+ }
210
+
211
+ if (import.meta.main) await main();
@@ -0,0 +1,101 @@
1
+ /**
2
+ * `bun run gate` — this repo's gate, run by the generation's shared runner.
3
+ *
4
+ * ## Where the argument went
5
+ *
6
+ * This repo's gate stopped being an `&&` chain on 2026-09-15 and became a dependency graph, and
7
+ * `src/verifyGraph.spec.ts` is the file that holds it to that — the stage set it may never
8
+ * shrink below, the two edges, and why `build` is a leaf. On 2026-09-20 the SCHEDULER moved to
9
+ * `$FORGE/tools/gate.ts` so the other twenty repos could have it too, and the stages moved to the
10
+ * `gate` block in `package.json`, which keeps `package.json` the one place every command is
11
+ * spelled. Read those two; this file only locates the tool.
12
+ *
13
+ * What the move buys this repo specifically is the SECOND run, not the first. One gate here is
14
+ * 33–65 s and has been since 2026-09-18 (the graph did that; `autopilot timings`' all-time median
15
+ * of 6.5 m is dominated by runs from before it, and is the wrong number to plan against). What
16
+ * this repo spends is 14.72 h — 58 % of every gate second this generation has ever spent, over 84
17
+ * runs across 41 agents — because the ledger says the median agent runs the gate TWICE and the
18
+ * supervisor runs it again after, on the same tree. A stamped run is 0.1 s. See
19
+ * `$FORGE/tools/gate.ts` for why the stamp is keyed on content and not on a clock.
20
+ *
21
+ * ## 🔴 Why this is a wrapper and not `bun ../../tools/gate.ts .`
22
+ *
23
+ * That spelling assumes this checkout sits at a fixed depth under the generation root, and a
24
+ * WORKTREE never does. It is the same argument, verbatim, as `scripts/paths.ts` — which is where
25
+ * it is written down, along with what it cost on 2026-09-17 — and the same two walks: up for
26
+ * `forge.env`, then via the primary checkout a worktree's `.git` file points at.
27
+ *
28
+ * 🔴 **No generation, no pass.** A gate that could not be located has not passed.
29
+ */
30
+ import { spawnSync } from "node:child_process";
31
+ import { existsSync } from "node:fs";
32
+ import { dirname, join, resolve } from "node:path";
33
+ import { fileURLToPath } from "node:url";
34
+
35
+ /** The one tool: the shared runner. The stages it runs are the `gate` block in `package.json`. */
36
+ const TOOLS = ["gate.ts"];
37
+
38
+ /** How far up either walk looks before giving up — a bound, so a misuse is `null` in ms. */
39
+ const MAX_HOPS = 16;
40
+
41
+ /** Walk up from `from` for a directory containing `marker`, or `null`. */
42
+ function walkUp(from: string, marker: string): string | null {
43
+ let dir = resolve(from);
44
+ for (let hops = 0; hops < MAX_HOPS; hops++) {
45
+ if (existsSync(join(dir, marker))) return dir;
46
+ const up = dirname(dir);
47
+ if (up === dir) return null;
48
+ dir = up;
49
+ }
50
+ return null;
51
+ }
52
+
53
+ /** The directory holding `forge.env` above `from`, or `null` when that is not inside a generation. */
54
+ function findForgeRoot(from: string): string | null {
55
+ return walkUp(from, "forge.env");
56
+ }
57
+
58
+ /** The generation above the checkout this WORKTREE was cut from, or `null` on anything unexpected. */
59
+ function viaWorktree(from: string): string | null {
60
+ try {
61
+ const git = spawnSync("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
62
+ cwd: from,
63
+ encoding: "utf8",
64
+ timeout: 5_000,
65
+ });
66
+ if (git.status !== 0) return null;
67
+ const gitDir = (git.stdout ?? "").trim();
68
+ if (!gitDir || !gitDir.startsWith("/")) return null;
69
+ // `<primary>/.git` → `<primary>`, then the ordinary walk up.
70
+ return findForgeRoot(dirname(gitDir));
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ const here = dirname(fileURLToPath(import.meta.url));
77
+ /** This checkout — the nearest ancestor holding a `package.json`, so it is right in a worktree. */
78
+ const repo = walkUp(here, "package.json");
79
+ const root = findForgeRoot(here) ?? viaWorktree(here);
80
+
81
+ if (!repo) {
82
+ console.error(`✗ no package.json above ${here}, so there is no repo to check.`);
83
+ process.exit(1);
84
+ }
85
+ if (!root) {
86
+ console.error("✗ this checkout is not inside a generation and is not a worktree of one, so");
87
+ console.error(` tools/{${TOOLS.join(",")}} cannot be located. Run it from a checkout under a`);
88
+ console.error(" generation, or from a worktree cut from one — a skipped check is not a passed one.");
89
+ process.exit(1);
90
+ }
91
+
92
+ for (const name of TOOLS) {
93
+ const tool = join(root, "tools", name);
94
+ if (!existsSync(tool)) {
95
+ console.error(`✗ ${tool} does not exist. The generation at ${root} has no ${name},`);
96
+ console.error(" so this repo cannot prove it obeys that law. That is a failure, not a skip.");
97
+ process.exit(1);
98
+ }
99
+ const result = spawnSync("bun", [tool, repo, ...process.argv.slice(2)], { stdio: "inherit" });
100
+ if ((result.status ?? 1) !== 0) process.exit(result.status ?? 1);
101
+ }