cursedbelt 1.0.0 → 2.3.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 (533) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/core/category/index.d.ts.map +1 -1
  3. package/dist/core/category/index.js +2 -1
  4. package/dist/core/category/index.js.map +1 -1
  5. package/dist/core/category/types.js +1 -1
  6. package/dist/core/category/types.js.map +1 -1
  7. package/dist/core/file-tree/fileTreeModel.d.ts +49 -0
  8. package/dist/core/file-tree/fileTreeModel.d.ts.map +1 -1
  9. package/dist/core/file-tree/fileTreeModel.js +84 -0
  10. package/dist/core/file-tree/fileTreeModel.js.map +1 -1
  11. package/dist/core/layout/index.js +1 -1
  12. package/dist/core/layout/index.js.map +1 -1
  13. package/dist/core/media/index.js +1 -1
  14. package/dist/core/media/index.js.map +1 -1
  15. package/dist/core/media/types.js +1 -1
  16. package/dist/core/media/types.js.map +1 -1
  17. package/dist/core/media/uploadLimits.js +1 -1
  18. package/dist/core/media/uploadLimits.js.map +1 -1
  19. package/dist/core/sharing/model.d.ts +1 -1
  20. package/dist/ctgr/index.js +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/react/activity-bar/ActivityBar.d.ts +17 -0
  24. package/dist/react/activity-bar/ActivityBar.d.ts.map +1 -1
  25. package/dist/react/activity-bar/ActivityBar.js.map +1 -1
  26. package/dist/react/analytics/index.d.ts +1 -1
  27. package/dist/react/analytics/index.js +1 -1
  28. package/dist/react/chat/MessageComposer.d.ts.map +1 -1
  29. package/dist/react/chat/MessageComposer.js +5 -4
  30. package/dist/react/chat/MessageComposer.js.map +1 -1
  31. package/dist/react/components/Button.d.ts.map +1 -1
  32. package/dist/react/components/Button.js +3 -2
  33. package/dist/react/components/Button.js.map +1 -1
  34. package/dist/react/components/Checkbox.d.ts +19 -3
  35. package/dist/react/components/Checkbox.d.ts.map +1 -1
  36. package/dist/react/components/Checkbox.js +29 -12
  37. package/dist/react/components/Checkbox.js.map +1 -1
  38. package/dist/react/components/CodeArea.d.ts.map +1 -1
  39. package/dist/react/components/CodeArea.js +2 -1
  40. package/dist/react/components/CodeArea.js.map +1 -1
  41. package/dist/react/components/Collapsible.d.ts.map +1 -1
  42. package/dist/react/components/Collapsible.js +2 -1
  43. package/dist/react/components/Collapsible.js.map +1 -1
  44. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  45. package/dist/react/components/ComboboxField.js +3 -2
  46. package/dist/react/components/ComboboxField.js.map +1 -1
  47. package/dist/react/components/CopyButton.d.ts.map +1 -1
  48. package/dist/react/components/CopyButton.js +2 -1
  49. package/dist/react/components/CopyButton.js.map +1 -1
  50. package/dist/react/components/DataTable/ColumnChecklist.d.ts.map +1 -1
  51. package/dist/react/components/DataTable/ColumnChecklist.js +2 -1
  52. package/dist/react/components/DataTable/ColumnChecklist.js.map +1 -1
  53. package/dist/react/components/DataTable/Pagination.d.ts.map +1 -1
  54. package/dist/react/components/DataTable/Pagination.js +2 -1
  55. package/dist/react/components/DataTable/Pagination.js.map +1 -1
  56. package/dist/react/components/DataTable/SortHeader.d.ts.map +1 -1
  57. package/dist/react/components/DataTable/SortHeader.js +2 -1
  58. package/dist/react/components/DataTable/SortHeader.js.map +1 -1
  59. package/dist/react/components/DataTable/TableFilterBuilder.d.ts +61 -0
  60. package/dist/react/components/DataTable/TableFilterBuilder.d.ts.map +1 -0
  61. package/dist/react/components/DataTable/{FilterBuilder.js → TableFilterBuilder.js} +26 -3
  62. package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -0
  63. package/dist/react/components/DataTable/Toolbar.d.ts +1 -1
  64. package/dist/react/components/DataTable/Toolbar.js +3 -3
  65. package/dist/react/components/DataTable/Toolbar.js.map +1 -1
  66. package/dist/react/components/DataTable/cells/LinkCell.d.ts.map +1 -1
  67. package/dist/react/components/DataTable/cells/LinkCell.js +2 -1
  68. package/dist/react/components/DataTable/cells/LinkCell.js.map +1 -1
  69. package/dist/react/components/DataTable/index.d.ts +1 -1
  70. package/dist/react/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/react/components/DataTable/index.js +4 -1
  72. package/dist/react/components/DataTable/index.js.map +1 -1
  73. package/dist/react/components/DragHandle.d.ts.map +1 -1
  74. package/dist/react/components/DragHandle.js +2 -1
  75. package/dist/react/components/DragHandle.js.map +1 -1
  76. package/dist/react/components/EmojiField.d.ts.map +1 -1
  77. package/dist/react/components/EmojiField.js +2 -1
  78. package/dist/react/components/EmojiField.js.map +1 -1
  79. package/dist/react/components/EventTimeline.d.ts +3 -2
  80. package/dist/react/components/EventTimeline.d.ts.map +1 -1
  81. package/dist/react/components/EventTimeline.js +3 -2
  82. package/dist/react/components/EventTimeline.js.map +1 -1
  83. package/dist/react/components/IconButton.d.ts +1 -1
  84. package/dist/react/components/IconButton.js +1 -1
  85. package/dist/react/components/InfoHint.d.ts.map +1 -1
  86. package/dist/react/components/InfoHint.js +5 -4
  87. package/dist/react/components/InfoHint.js.map +1 -1
  88. package/dist/react/components/InheritBadge.js +1 -1
  89. package/dist/react/components/InheritBadge.js.map +1 -1
  90. package/dist/react/components/InlineEditableText.d.ts.map +1 -1
  91. package/dist/react/components/InlineEditableText.js +2 -1
  92. package/dist/react/components/InlineEditableText.js.map +1 -1
  93. package/dist/react/components/MeterList.d.ts.map +1 -1
  94. package/dist/react/components/MeterList.js +2 -1
  95. package/dist/react/components/MeterList.js.map +1 -1
  96. package/dist/react/components/PathText.d.ts +2 -2
  97. package/dist/react/components/PathText.d.ts.map +1 -1
  98. package/dist/react/components/PathText.js +2 -1
  99. package/dist/react/components/PathText.js.map +1 -1
  100. package/dist/react/components/RatingField.d.ts.map +1 -1
  101. package/dist/react/components/RatingField.js +2 -1
  102. package/dist/react/components/RatingField.js.map +1 -1
  103. package/dist/react/components/SecretInput.js +3 -2
  104. package/dist/react/components/SecretInput.js.map +1 -1
  105. package/dist/react/components/SegmentedControl.d.ts.map +1 -1
  106. package/dist/react/components/SegmentedControl.js +2 -1
  107. package/dist/react/components/SegmentedControl.js.map +1 -1
  108. package/dist/react/components/StarRating.d.ts.map +1 -1
  109. package/dist/react/components/StarRating.js +9 -5
  110. package/dist/react/components/StarRating.js.map +1 -1
  111. package/dist/react/components/StatStrip.d.ts.map +1 -1
  112. package/dist/react/components/StatStrip.js +2 -1
  113. package/dist/react/components/StatStrip.js.map +1 -1
  114. package/dist/react/components/StatTile.d.ts.map +1 -1
  115. package/dist/react/components/StatTile.js +3 -2
  116. package/dist/react/components/StatTile.js.map +1 -1
  117. package/dist/react/components/Tabs.d.ts.map +1 -1
  118. package/dist/react/components/Tabs.js +2 -1
  119. package/dist/react/components/Tabs.js.map +1 -1
  120. package/dist/react/components/TruncatedText.d.ts +2 -1
  121. package/dist/react/components/TruncatedText.d.ts.map +1 -1
  122. package/dist/react/components/TruncatedText.js +2 -1
  123. package/dist/react/components/TruncatedText.js.map +1 -1
  124. package/dist/react/components/calendar/MonthGrid.d.ts.map +1 -1
  125. package/dist/react/components/calendar/MonthGrid.js +2 -1
  126. package/dist/react/components/calendar/MonthGrid.js.map +1 -1
  127. package/dist/react/components/calendar/WeekView.d.ts.map +1 -1
  128. package/dist/react/components/calendar/WeekView.js +2 -1
  129. package/dist/react/components/calendar/WeekView.js.map +1 -1
  130. package/dist/react/components/revealOnHover.d.ts.map +1 -1
  131. package/dist/react/components/revealOnHover.js +2 -1
  132. package/dist/react/components/revealOnHover.js.map +1 -1
  133. package/dist/react/file-tree/FileTree.d.ts +50 -1
  134. package/dist/react/file-tree/FileTree.d.ts.map +1 -1
  135. package/dist/react/file-tree/FileTree.js +234 -6
  136. package/dist/react/file-tree/FileTree.js.map +1 -1
  137. package/dist/react/file-tree/fileTree.css +52 -0
  138. package/dist/react/filter-rail/FilterRail.d.ts.map +1 -1
  139. package/dist/react/filter-rail/FilterRail.js +5 -4
  140. package/dist/react/filter-rail/FilterRail.js.map +1 -1
  141. package/dist/react/folder-tree/FolderTreeRail.d.ts.map +1 -1
  142. package/dist/react/folder-tree/FolderTreeRail.js +2 -1
  143. package/dist/react/folder-tree/FolderTreeRail.js.map +1 -1
  144. package/dist/react/index.d.ts +5 -1
  145. package/dist/react/index.d.ts.map +1 -1
  146. package/dist/react/index.js +5 -1
  147. package/dist/react/index.js.map +1 -1
  148. package/dist/react/layoutEngine/index.js +1 -1
  149. package/dist/react/layoutEngine/index.js.map +1 -1
  150. package/dist/react/lib/field.d.ts.map +1 -1
  151. package/dist/react/lib/field.js +3 -2
  152. package/dist/react/lib/field.js.map +1 -1
  153. package/dist/react/lib/floatingStyles.d.ts.map +1 -1
  154. package/dist/react/lib/floatingStyles.js +2 -1
  155. package/dist/react/lib/floatingStyles.js.map +1 -1
  156. package/dist/react/lib/tapTarget.d.ts +96 -0
  157. package/dist/react/lib/tapTarget.d.ts.map +1 -0
  158. package/dist/react/lib/tapTarget.js +96 -0
  159. package/dist/react/lib/tapTarget.js.map +1 -0
  160. package/dist/react/media/VideoTrimmer.d.ts +1 -1
  161. package/dist/react/media/VideoTrimmer.js +1 -1
  162. package/dist/react/media/denseGallery.css +3 -3
  163. package/dist/react/media/ffmpegWasm.js +2 -2
  164. package/dist/react/media/ffmpegWasm.js.map +1 -1
  165. package/dist/react/media/videoPlayer.css +42 -0
  166. package/dist/react/namespace/NamespaceTargetCapsule.d.ts +2 -2
  167. package/dist/react/namespace/NamespaceTargetCapsule.d.ts.map +1 -1
  168. package/dist/react/nav/BreadcrumbTrail.d.ts.map +1 -1
  169. package/dist/react/nav/BreadcrumbTrail.js +4 -3
  170. package/dist/react/nav/BreadcrumbTrail.js.map +1 -1
  171. package/dist/react/nav/HubTileGrid.d.ts.map +1 -1
  172. package/dist/react/nav/HubTileGrid.js +2 -1
  173. package/dist/react/nav/HubTileGrid.js.map +1 -1
  174. package/dist/react/nav/SideNav.d.ts.map +1 -1
  175. package/dist/react/nav/SideNav.js +4 -3
  176. package/dist/react/nav/SideNav.js.map +1 -1
  177. package/dist/react/nav/SideNavCustomize.d.ts.map +1 -1
  178. package/dist/react/nav/SideNavCustomize.js +2 -1
  179. package/dist/react/nav/SideNavCustomize.js.map +1 -1
  180. package/dist/react/palette/CommandPalette.d.ts.map +1 -1
  181. package/dist/react/palette/CommandPalette.js +3 -2
  182. package/dist/react/palette/CommandPalette.js.map +1 -1
  183. package/dist/server/drivers/pooledControlStores.pg.test.js +1 -0
  184. package/dist/server/drivers/pooledControlStores.pg.test.js.map +1 -1
  185. package/dist/server/drivers/pooledIdentityStore.pg.test.js +1 -0
  186. package/dist/server/drivers/pooledIdentityStore.pg.test.js.map +1 -1
  187. package/dist/server/drivers/retentionPolicy.pg.test.js +1 -0
  188. package/dist/server/drivers/retentionPolicy.pg.test.js.map +1 -1
  189. package/dist/server/guard/argon2Binding.d.ts +1 -1
  190. package/dist/server/guard/argon2Binding.js +1 -1
  191. package/dist/server/incidents/store.d.ts +3 -3
  192. package/dist/server/index.js +1 -1
  193. package/dist/server/index.js.map +1 -1
  194. package/dist/server/master-lock/masterLock.d.ts +1 -1
  195. package/dist/server/media-bun/index.js +1 -1
  196. package/dist/server/media-bun/index.js.map +1 -1
  197. package/dist/server/paths/appDataHome.d.ts +20 -0
  198. package/dist/server/paths/appDataHome.d.ts.map +1 -0
  199. package/dist/server/paths/appDataHome.js +69 -0
  200. package/dist/server/paths/appDataHome.js.map +1 -0
  201. package/dist/server/retention/archive.d.ts +3 -4
  202. package/dist/server/retention/archive.d.ts.map +1 -1
  203. package/dist/server/retention/archive.js +20 -15
  204. package/dist/server/retention/archive.js.map +1 -1
  205. package/dist/server/retention/index.d.ts +1 -1
  206. package/dist/server/retention/index.js +1 -1
  207. package/dist/server/retention/policy.d.ts +2 -2
  208. package/dist/server/retention/policy.d.ts.map +1 -1
  209. package/dist/server/retention/policy.js +1 -1
  210. package/dist/server/retention/store.d.ts.map +1 -1
  211. package/dist/server/retention/store.js +27 -20
  212. package/dist/server/retention/store.js.map +1 -1
  213. package/dist/server/runtime/localHost.d.ts +10 -5
  214. package/dist/server/runtime/localHost.d.ts.map +1 -1
  215. package/dist/server/runtime/localHost.js +12 -8
  216. package/dist/server/runtime/localHost.js.map +1 -1
  217. package/dist/server/runtime/meterRollup.pg.test.js +1 -0
  218. package/dist/server/runtime/meterRollup.pg.test.js.map +1 -1
  219. package/dist/server/runtime/recipe.d.ts +4 -4
  220. package/dist/server/runtime/retentionJob.pg.test.js +1 -0
  221. package/dist/server/runtime/retentionJob.pg.test.js.map +1 -1
  222. package/dist/server/search/pgSearchProvider.pg.test.js +1 -0
  223. package/dist/server/search/pgSearchProvider.pg.test.js.map +1 -1
  224. package/dist/shared/errors.d.ts +1 -1
  225. package/dist/shared/errors.js +1 -1
  226. package/dist/styles-static.css +391 -0
  227. package/dist/styles.css +27 -0
  228. package/package.json +19 -167
  229. package/scripts/generateStaticStyles.ts +122 -0
  230. package/scripts/publicSurface.ts +455 -0
  231. package/scripts/testTmpRoot.ts +34 -5
  232. package/src/client/index.ts +1 -1
  233. package/src/core/category/index.ts +2 -1
  234. package/src/core/category/types.ts +1 -1
  235. package/src/core/file-tree/fileTreeModel.spec.ts +134 -0
  236. package/src/core/file-tree/fileTreeModel.ts +104 -0
  237. package/src/core/layout/index.ts +1 -1
  238. package/src/core/media/index.ts +1 -1
  239. package/src/core/media/types.ts +1 -1
  240. package/src/core/media/uploadLimits.ts +1 -1
  241. package/src/core/sharing/model.ts +1 -1
  242. package/src/ctgr/index.ts +1 -1
  243. package/src/declaredDepsAreImported.spec.ts +87 -0
  244. package/src/demoFixture.spec.ts +133 -0
  245. package/src/index.ts +1 -1
  246. package/src/lockfileIsTracked.spec.ts +50 -0
  247. package/src/namedSubpathsResolve.spec.ts +119 -0
  248. package/src/publicSurface.spec.ts +72 -0
  249. package/src/react/activity-bar/ActivityBar.tsx +17 -0
  250. package/src/react/analytics/index.ts +1 -1
  251. package/src/react/chat/MessageComposer.tsx +5 -4
  252. package/src/react/components/Button.tsx +3 -2
  253. package/src/react/components/Checkbox.spec.tsx +51 -0
  254. package/src/react/components/Checkbox.tsx +68 -26
  255. package/src/react/components/CodeArea.tsx +2 -1
  256. package/src/react/components/CodeChip.spec.tsx +2 -2
  257. package/src/react/components/Collapsible.tsx +2 -1
  258. package/src/react/components/ComboboxField.tsx +3 -2
  259. package/src/react/components/CopyButton.tsx +2 -1
  260. package/src/react/components/CopyableText.spec.tsx +1 -1
  261. package/src/react/components/DataTable/ColumnChecklist.tsx +2 -1
  262. package/src/react/components/DataTable/Pagination.tsx +2 -1
  263. package/src/react/components/DataTable/SortHeader.tsx +2 -1
  264. package/src/react/components/DataTable/{FilterBuilder.tsx → TableFilterBuilder.tsx} +33 -5
  265. package/src/react/components/DataTable/Toolbar.tsx +3 -3
  266. package/src/react/components/DataTable/cells/LinkCell.tsx +2 -1
  267. package/src/react/components/DataTable/index.ts +8 -1
  268. package/src/react/components/DragHandle.tsx +2 -1
  269. package/src/react/components/EmojiField.tsx +2 -1
  270. package/src/react/components/EventTimeline.tsx +3 -2
  271. package/src/react/components/FileLocation.spec.tsx +1 -1
  272. package/src/react/components/IconButton.tsx +1 -1
  273. package/src/react/components/InfoHint.tsx +5 -4
  274. package/src/react/components/InheritBadge.tsx +1 -1
  275. package/src/react/components/InlineEditableText.tsx +2 -1
  276. package/src/react/components/MeterList.tsx +2 -1
  277. package/src/react/components/PathText.tsx +4 -3
  278. package/src/react/components/RatingField.tsx +2 -1
  279. package/src/react/components/SecretInput.tsx +3 -3
  280. package/src/react/components/SegmentedControl.tsx +2 -2
  281. package/src/react/components/StarRating.spec.tsx +2 -2
  282. package/src/react/components/StarRating.tsx +9 -5
  283. package/src/react/components/StatStrip.tsx +2 -1
  284. package/src/react/components/StatTile.tsx +3 -3
  285. package/src/react/components/Tabs.spec.tsx +3 -2
  286. package/src/react/components/Tabs.tsx +2 -1
  287. package/src/react/components/TruncatedText.tsx +2 -1
  288. package/src/react/components/calendar/MonthGrid.spec.tsx +2 -1
  289. package/src/react/components/calendar/MonthGrid.tsx +2 -1
  290. package/src/react/components/calendar/WeekView.tsx +2 -1
  291. package/src/react/components/revealOnHover.ts +3 -2
  292. package/src/react/file-tree/FileTree.spec.tsx +248 -0
  293. package/src/react/file-tree/FileTree.tsx +304 -4
  294. package/src/react/file-tree/fileTree.css +52 -0
  295. package/src/react/file-tree/fileTreeGeometry.fixture.json +151 -0
  296. package/src/react/file-tree/fileTreeGeometry.spec.ts +33 -52
  297. package/src/react/filter-rail/FilterRail.spec.tsx +2 -1
  298. package/src/react/filter-rail/FilterRail.tsx +5 -4
  299. package/src/react/folder-tree/FolderTreeRail.tsx +2 -1
  300. package/src/react/index.ts +13 -3
  301. package/src/react/layoutEngine/index.ts +1 -1
  302. package/src/react/layoutEngine/types.ts +1 -1
  303. package/src/react/lib/field.ts +4 -2
  304. package/src/react/lib/floatingStyles.spec.ts +2 -1
  305. package/src/react/lib/floatingStyles.ts +3 -1
  306. package/src/react/lib/tapTarget.ts +100 -0
  307. package/src/react/media/MaskPainter.tsx +2 -2
  308. package/src/react/media/VideoTrimmer.tsx +1 -1
  309. package/src/react/media/denseGallery.css +3 -3
  310. package/src/react/media/ffmpegWasm.ts +2 -2
  311. package/src/react/media/videoPlayer.css +42 -0
  312. package/src/react/namespace/NamespaceTargetCapsule.tsx +2 -2
  313. package/src/react/nav/BreadcrumbTrail.tsx +4 -3
  314. package/src/react/nav/HubTileGrid.tsx +2 -1
  315. package/src/react/nav/SideNav.tsx +4 -3
  316. package/src/react/nav/SideNavCustomize.tsx +2 -1
  317. package/src/react/palette/CommandPalette.tsx +3 -2
  318. package/src/server/ctgr.ts +1 -1
  319. package/src/server/drivers/pooledControlStores.pg.test.ts +1 -0
  320. package/src/server/drivers/pooledIdentityStore.pg.test.ts +1 -0
  321. package/src/server/drivers/retentionPolicy.pg.test.ts +1 -0
  322. package/src/server/guard/argon2Binding.ts +1 -1
  323. package/src/server/incidents/store.ts +3 -3
  324. package/src/server/index.ts +1 -1
  325. package/src/server/master-lock/masterLock.spec.ts +18 -2
  326. package/src/server/master-lock/masterLock.ts +1 -1
  327. package/src/server/media-bun/image.spec.ts +1 -0
  328. package/src/server/media-bun/index.ts +1 -1
  329. package/src/server/media-bun/video.spec.ts +1 -0
  330. package/src/server/paths/appDataHome.spec.ts +87 -0
  331. package/src/server/paths/appDataHome.ts +84 -0
  332. package/src/server/retention/archive.spec.ts +26 -4
  333. package/src/server/retention/archive.ts +20 -15
  334. package/src/server/retention/index.ts +1 -1
  335. package/src/server/retention/policy.ts +2 -2
  336. package/src/server/retention/store.spec.ts +38 -10
  337. package/src/server/retention/store.ts +26 -19
  338. package/src/server/runtime/localHost.spec.ts +22 -3
  339. package/src/server/runtime/localHost.ts +12 -9
  340. package/src/server/runtime/meterRollup.pg.test.ts +1 -0
  341. package/src/server/runtime/recipe.ts +4 -4
  342. package/src/server/runtime/retentionJob.pg.test.ts +1 -0
  343. package/src/server/search/pgSearchProvider.pg.test.ts +1 -0
  344. package/src/server/storage/binaryServerProcessing.integration.spec.ts +6 -2
  345. package/src/server/storage/chunked.integration.spec.ts +5 -2
  346. package/src/server/storage/fileUploadClient-chunked.integration.spec.ts +5 -2
  347. package/src/server/storage/files/adapter.photo.display.spec.ts +1 -0
  348. package/src/server/storage/imageThumbnail.spec.ts +1 -0
  349. package/src/server/storage/transcode.integration.spec.ts +5 -2
  350. package/src/server/storage/videoProcessor.posterOnly.spec.ts +1 -0
  351. package/src/shared/errors.ts +1 -1
  352. package/src/skippedTestsAreAnswered.spec.ts +215 -0
  353. package/src/styles-static.css +391 -0
  354. package/src/styles.css +27 -0
  355. package/src/stylesStaticMatches.spec.ts +134 -0
  356. package/src/tapTargetStylesheet.spec.ts +150 -0
  357. package/src/testTmpRoot.spec.ts +102 -0
  358. package/dist/core/duplicates/index.d.ts +0 -116
  359. package/dist/core/duplicates/index.d.ts.map +0 -1
  360. package/dist/core/duplicates/index.js +0 -178
  361. package/dist/core/duplicates/index.js.map +0 -1
  362. package/dist/core/namespace/helpers.d.ts +0 -14
  363. package/dist/core/namespace/helpers.d.ts.map +0 -1
  364. package/dist/core/namespace/helpers.js +0 -29
  365. package/dist/core/namespace/helpers.js.map +0 -1
  366. package/dist/core/namespace/index.d.ts +0 -4
  367. package/dist/core/namespace/index.d.ts.map +0 -1
  368. package/dist/core/namespace/index.js +0 -6
  369. package/dist/core/namespace/index.js.map +0 -1
  370. package/dist/core/namespace/memoryStore.d.ts +0 -19
  371. package/dist/core/namespace/memoryStore.d.ts.map +0 -1
  372. package/dist/core/namespace/memoryStore.js +0 -70
  373. package/dist/core/namespace/memoryStore.js.map +0 -1
  374. package/dist/core/namespace/types.d.ts +0 -44
  375. package/dist/core/namespace/types.d.ts.map +0 -1
  376. package/dist/core/namespace/types.js +0 -8
  377. package/dist/core/namespace/types.js.map +0 -1
  378. package/dist/game/core/DisposeRegistry.d.ts +0 -42
  379. package/dist/game/core/DisposeRegistry.d.ts.map +0 -1
  380. package/dist/game/core/DisposeRegistry.js +0 -67
  381. package/dist/game/core/DisposeRegistry.js.map +0 -1
  382. package/dist/game/core/drawBudget.d.ts +0 -26
  383. package/dist/game/core/drawBudget.d.ts.map +0 -1
  384. package/dist/game/core/drawBudget.js +0 -55
  385. package/dist/game/core/drawBudget.js.map +0 -1
  386. package/dist/game/core/fixedTimestep.d.ts +0 -38
  387. package/dist/game/core/fixedTimestep.d.ts.map +0 -1
  388. package/dist/game/core/fixedTimestep.js +0 -47
  389. package/dist/game/core/fixedTimestep.js.map +0 -1
  390. package/dist/game/core/index.d.ts +0 -9
  391. package/dist/game/core/index.d.ts.map +0 -1
  392. package/dist/game/core/index.js +0 -8
  393. package/dist/game/core/index.js.map +0 -1
  394. package/dist/game/core/inputCollector.d.ts +0 -82
  395. package/dist/game/core/inputCollector.d.ts.map +0 -1
  396. package/dist/game/core/inputCollector.js +0 -176
  397. package/dist/game/core/inputCollector.js.map +0 -1
  398. package/dist/game/core/resizeCanvas.d.ts +0 -19
  399. package/dist/game/core/resizeCanvas.d.ts.map +0 -1
  400. package/dist/game/core/resizeCanvas.js +0 -29
  401. package/dist/game/core/resizeCanvas.js.map +0 -1
  402. package/dist/game/react/index.d.ts +0 -3
  403. package/dist/game/react/index.d.ts.map +0 -1
  404. package/dist/game/react/index.js +0 -5
  405. package/dist/game/react/index.js.map +0 -1
  406. package/dist/game/react/useGameEngine.d.ts +0 -64
  407. package/dist/game/react/useGameEngine.d.ts.map +0 -1
  408. package/dist/game/react/useGameEngine.js +0 -78
  409. package/dist/game/react/useGameEngine.js.map +0 -1
  410. package/dist/react/canvas/CanvasNavHUD.d.ts +0 -64
  411. package/dist/react/canvas/CanvasNavHUD.d.ts.map +0 -1
  412. package/dist/react/canvas/CanvasNavHUD.js +0 -58
  413. package/dist/react/canvas/CanvasNavHUD.js.map +0 -1
  414. package/dist/react/canvas/fitLabel.d.ts +0 -53
  415. package/dist/react/canvas/fitLabel.d.ts.map +0 -1
  416. package/dist/react/canvas/fitLabel.js +0 -104
  417. package/dist/react/canvas/fitLabel.js.map +0 -1
  418. package/dist/react/canvas/index.d.ts +0 -4
  419. package/dist/react/canvas/index.d.ts.map +0 -1
  420. package/dist/react/canvas/index.js +0 -4
  421. package/dist/react/canvas/index.js.map +0 -1
  422. package/dist/react/canvas/lod.d.ts +0 -40
  423. package/dist/react/canvas/lod.d.ts.map +0 -1
  424. package/dist/react/canvas/lod.js +0 -37
  425. package/dist/react/canvas/lod.js.map +0 -1
  426. package/dist/react/components/DataTable/FilterBuilder.d.ts +0 -38
  427. package/dist/react/components/DataTable/FilterBuilder.d.ts.map +0 -1
  428. package/dist/react/components/DataTable/FilterBuilder.js.map +0 -1
  429. package/dist/react/seo/HeadProvider.d.ts +0 -14
  430. package/dist/react/seo/HeadProvider.d.ts.map +0 -1
  431. package/dist/react/seo/HeadProvider.js +0 -44
  432. package/dist/react/seo/HeadProvider.js.map +0 -1
  433. package/dist/react/seo/applyHeadToDocument.d.ts +0 -3
  434. package/dist/react/seo/applyHeadToDocument.d.ts.map +0 -1
  435. package/dist/react/seo/applyHeadToDocument.js +0 -66
  436. package/dist/react/seo/applyHeadToDocument.js.map +0 -1
  437. package/dist/react/seo/index.d.ts +0 -3
  438. package/dist/react/seo/index.d.ts.map +0 -1
  439. package/dist/react/seo/index.js +0 -7
  440. package/dist/react/seo/index.js.map +0 -1
  441. package/dist/react/timeline/ClipView.d.ts +0 -29
  442. package/dist/react/timeline/ClipView.d.ts.map +0 -1
  443. package/dist/react/timeline/ClipView.js +0 -53
  444. package/dist/react/timeline/ClipView.js.map +0 -1
  445. package/dist/react/timeline/Playhead.d.ts +0 -16
  446. package/dist/react/timeline/Playhead.d.ts.map +0 -1
  447. package/dist/react/timeline/Playhead.js +0 -26
  448. package/dist/react/timeline/Playhead.js.map +0 -1
  449. package/dist/react/timeline/TimeRuler.d.ts +0 -21
  450. package/dist/react/timeline/TimeRuler.d.ts.map +0 -1
  451. package/dist/react/timeline/TimeRuler.js +0 -31
  452. package/dist/react/timeline/TimeRuler.js.map +0 -1
  453. package/dist/react/timeline/TimelineSurface.d.ts +0 -29
  454. package/dist/react/timeline/TimelineSurface.d.ts.map +0 -1
  455. package/dist/react/timeline/TimelineSurface.js +0 -56
  456. package/dist/react/timeline/TimelineSurface.js.map +0 -1
  457. package/dist/react/timeline/TrackLane.d.ts +0 -31
  458. package/dist/react/timeline/TrackLane.d.ts.map +0 -1
  459. package/dist/react/timeline/TrackLane.js +0 -32
  460. package/dist/react/timeline/TrackLane.js.map +0 -1
  461. package/dist/react/timeline/index.d.ts +0 -6
  462. package/dist/react/timeline/index.d.ts.map +0 -1
  463. package/dist/react/timeline/index.js +0 -12
  464. package/dist/react/timeline/index.js.map +0 -1
  465. package/dist/server/private-media/index.d.ts +0 -7
  466. package/dist/server/private-media/index.d.ts.map +0 -1
  467. package/dist/server/private-media/index.js +0 -13
  468. package/dist/server/private-media/index.js.map +0 -1
  469. package/dist/server/seo/index.d.ts +0 -3
  470. package/dist/server/seo/index.d.ts.map +0 -1
  471. package/dist/server/seo/index.js +0 -6
  472. package/dist/server/seo/index.js.map +0 -1
  473. package/dist/server/seo/mountSeoRoutes.d.ts +0 -9
  474. package/dist/server/seo/mountSeoRoutes.d.ts.map +0 -1
  475. package/dist/server/seo/mountSeoRoutes.js +0 -19
  476. package/dist/server/seo/mountSeoRoutes.js.map +0 -1
  477. package/dist/server/seo/serveHeadInjectedIndex.d.ts +0 -9
  478. package/dist/server/seo/serveHeadInjectedIndex.d.ts.map +0 -1
  479. package/dist/server/seo/serveHeadInjectedIndex.js +0 -20
  480. package/dist/server/seo/serveHeadInjectedIndex.js.map +0 -1
  481. package/dist/upload.d.ts +0 -148
  482. package/dist/upload.d.ts.map +0 -1
  483. package/dist/upload.js +0 -159
  484. package/dist/upload.js.map +0 -1
  485. package/dist/verify/runtime/index.d.ts +0 -16
  486. package/dist/verify/runtime/index.d.ts.map +0 -1
  487. package/dist/verify/runtime/index.js +0 -16
  488. package/dist/verify/runtime/index.js.map +0 -1
  489. package/scripts/demoCheck.ts +0 -42
  490. package/src/core/duplicates/index.spec.ts +0 -116
  491. package/src/core/duplicates/index.ts +0 -203
  492. package/src/core/namespace/helpers.ts +0 -31
  493. package/src/core/namespace/index.ts +0 -12
  494. package/src/core/namespace/memoryStore.ts +0 -77
  495. package/src/core/namespace/namespace.spec.ts +0 -117
  496. package/src/core/namespace/types.ts +0 -53
  497. package/src/game/core/DisposeRegistry.spec.ts +0 -53
  498. package/src/game/core/DisposeRegistry.ts +0 -70
  499. package/src/game/core/drawBudget.spec.ts +0 -51
  500. package/src/game/core/drawBudget.ts +0 -75
  501. package/src/game/core/fixedTimestep.spec.ts +0 -91
  502. package/src/game/core/fixedTimestep.ts +0 -79
  503. package/src/game/core/index.ts +0 -16
  504. package/src/game/core/inputCollector.spec.ts +0 -29
  505. package/src/game/core/inputCollector.ts +0 -245
  506. package/src/game/core/resizeCanvas.ts +0 -31
  507. package/src/game/react/index.ts +0 -10
  508. package/src/game/react/useGameEngine.ts +0 -125
  509. package/src/react/canvas/CanvasNavHUD.spec.tsx +0 -62
  510. package/src/react/canvas/CanvasNavHUD.tsx +0 -210
  511. package/src/react/canvas/fitLabel.spec.ts +0 -82
  512. package/src/react/canvas/fitLabel.ts +0 -150
  513. package/src/react/canvas/index.ts +0 -15
  514. package/src/react/canvas/lod.ts +0 -53
  515. package/src/react/seo/HeadProvider.tsx +0 -67
  516. package/src/react/seo/applyHeadToDocument.ts +0 -73
  517. package/src/react/seo/index.ts +0 -12
  518. package/src/react/seo/seo.spec.tsx +0 -101
  519. package/src/react/timeline/ClipView.tsx +0 -146
  520. package/src/react/timeline/Playhead.tsx +0 -63
  521. package/src/react/timeline/TimeRuler.tsx +0 -85
  522. package/src/react/timeline/TimelineSurface.tsx +0 -157
  523. package/src/react/timeline/TrackLane.tsx +0 -87
  524. package/src/react/timeline/index.ts +0 -12
  525. package/src/react/timeline/timeline.spec.tsx +0 -175
  526. package/src/server/private-media/index.ts +0 -45
  527. package/src/server/seo/index.ts +0 -8
  528. package/src/server/seo/mountSeoRoutes.ts +0 -37
  529. package/src/server/seo/seo.spec.ts +0 -128
  530. package/src/server/seo/serveHeadInjectedIndex.ts +0 -36
  531. package/src/upload.spec.ts +0 -300
  532. package/src/upload.ts +0 -288
  533. package/src/verify/runtime/index.ts +0 -64
@@ -27,15 +27,22 @@
27
27
  * back up, copy to a box, or read at a glance.
28
28
  *
29
29
  * ── Where it lives ──────────────────────────────────────────────────────────
30
- * `~/.app-managed/retention` on this Mac — the App_Managed_Home contract's spot
31
- * for outside-repo state, and shared by every local app so the station sees one
32
- * fleet. A deployed box has no `~/.app-managed` and (under `ProtectSystem=strict`)
33
- * only its data dir is writable, so it falls back to `$APP_DATA_DIR/retention`:
34
- * the app still sweeps on the same code and the same defaults, and a station
35
- * instance on that box reads that box's fleet. The resolution probes
36
- * WRITABILITY rather than assuming, because the failure it prevents — an app
37
- * whose every publish silently EROFS-es — is invisible until someone asks why
38
- * the UI is empty.
30
+ * `<app-data-home>/retention` — one root shared by every local app, so the
31
+ * station sees one fleet. The home is CONFIGURATION ({@link resolveAppDataHome}):
32
+ * `$APP_DATA_HOME` when a machine keeps every app's data under one root, else the
33
+ * OS's own convention (`$XDG_DATA_HOME`, `~/Library/Application Support`).
34
+ *
35
+ * 🔴 It was `~/<a private dotfolder>` until 2026-09-13, hardcoded, in a PUBLISHED
36
+ * package — so anyone who installed cursedbelt got a library hunting for one
37
+ * person's directory layout. A library may know what its caller told it and what
38
+ * the OS says; it may not know the name of a folder in somebody's home.
39
+ *
40
+ * A deployed box under `ProtectSystem=strict` has only its own data dir writable,
41
+ * so it falls back to `$APP_DATA_DIR/retention`: the app still sweeps on the same
42
+ * code and the same defaults, and a station instance on that box reads that box's
43
+ * fleet. The resolution probes WRITABILITY rather than assuming, because the
44
+ * failure it prevents — an app whose every publish silently EROFS-es — is
45
+ * invisible until someone asks why the UI is empty.
39
46
  */
40
47
  import {
41
48
  existsSync,
@@ -46,8 +53,8 @@ import {
46
53
  rmSync,
47
54
  writeFileSync,
48
55
  } from "node:fs";
49
- import { homedir } from "node:os";
50
56
  import { join } from "node:path";
57
+ import { APP_DATA_HOME_ENV, resolveAppDataHome } from "../paths/appDataHome";
51
58
  import type { RetentionDeclaration, RetentionOverride } from "./policy";
52
59
  import { retentionKey } from "./policy";
53
60
 
@@ -155,15 +162,15 @@ export function resolveRetentionHome(
155
162
  if (cachedHome) return cachedHome;
156
163
  const candidates: string[] = [];
157
164
  if (env.RETENTION_HOME) candidates.push(env.RETENTION_HOME);
158
- if (env.APP_MANAGED_HOME) candidates.push(join(env.APP_MANAGED_HOME, "retention"));
159
- // `env.HOME` rather than `homedir()` alone so a caller passing an env object
160
- // gets a resolution it can actually control — the tests need to reason about a
161
- // machine WITHOUT a shared app-managed home, which is every deployed box.
162
- const conventional = join(env.HOME ?? homedir(), ".app-managed");
163
- // Only prefer the shared Mac home when it already exists: on a deployed box
164
- // creating it would either fail (read-only namespace) or strand a publication
165
- // somewhere no station instance looks.
166
- if (existsSync(conventional)) candidates.push(join(conventional, "retention"));
165
+ // An explicitly CONFIGURED home is used whether or not it exists yet — the
166
+ // operator naming it is the statement that it is the right place.
167
+ const configured = env[APP_DATA_HOME_ENV]?.trim();
168
+ if (configured) candidates.push(join(configured, "retention"));
169
+ const conventional = resolveAppDataHome({ env });
170
+ // The OS convention is only PREFERRED when it is already there: on a deployed
171
+ // box creating it would either fail (read-only namespace) or strand a
172
+ // publication somewhere no station instance looks.
173
+ if (!configured && existsSync(conventional)) candidates.push(join(conventional, "retention"));
167
174
  if (env.APP_DATA_DIR) candidates.push(join(env.APP_DATA_DIR, "retention"));
168
175
  candidates.push(join(conventional, "retention"));
169
176
 
@@ -9,6 +9,7 @@ import { tmpdir } from 'node:os';
9
9
  import path from 'node:path';
10
10
  import type { Argon2idDeriver } from 'cwip/guard';
11
11
  import { setArgon2idDeriver } from 'cwip/guard';
12
+ import { resolveAppDataHome } from '../paths/appDataHome';
12
13
  import {
13
14
  createLocalDevServices,
14
15
  createLocalGuardServices,
@@ -29,16 +30,34 @@ afterEach(() => {
29
30
  });
30
31
 
31
32
  describe('resolveAppDataRoot', () => {
32
- it('hangs off the ONE app-managed home, never a bespoke ~/.<app>', () => {
33
- const root = resolveAppDataRoot({ appId: 'demo', env: { APP_MANAGED_HOME: '/srv/managed' } });
33
+ it('hangs off the ONE configured app-data home, never a bespoke ~/.<app>', () => {
34
+ const root = resolveAppDataRoot({ appId: 'demo', env: { APP_DATA_HOME: '/srv/managed' } });
34
35
  expect(root).toBe(path.join('/srv/managed', 'instances', 'demo'));
35
36
  });
36
37
 
37
38
  it('lets an explicit override win outright', () => {
38
- expect(resolveAppDataRoot({ appId: 'demo', override: '/data/demo', env: { APP_MANAGED_HOME: '/srv' } })).toBe(
39
+ expect(resolveAppDataRoot({ appId: 'demo', override: '/data/demo', env: { APP_DATA_HOME: '/srv' } })).toBe(
39
40
  '/data/demo',
40
41
  );
41
42
  });
43
+
44
+ /*
45
+ * 🔴 With nothing configured it lands on the OS's convention, NOT on a folder
46
+ * this library invented in somebody's home. That was the published defect
47
+ * (2026-09-13): `cursedbelt@1.0.0` resolved the previous generation's private
48
+ * state root for every installer of the package.
49
+ */
50
+ it("falls back to the OS convention, not to anybody's private folder", () => {
51
+ const root = resolveAppDataRoot({ appId: 'demo', env: { HOME: '/home/nobody' } });
52
+ expect(root).toBe(path.join(resolveAppDataHome({ env: { HOME: '/home/nobody' } }), 'instances', 'demo'));
53
+ expect(root).not.toContain('app-managed');
54
+ expect(root.startsWith('/home/nobody/')).toBe(true);
55
+ });
56
+
57
+ it('ignores the previous generation env var entirely', () => {
58
+ const env = { HOME: '/home/nobody', APP_MANAGED_HOME: '/nowhere/inherited' };
59
+ expect(resolveAppDataRoot({ appId: 'demo', env })).not.toContain('/nowhere/inherited');
60
+ });
42
61
  });
43
62
 
44
63
  describe('loadOrMintKeyFile', () => {
@@ -12,8 +12,10 @@
12
12
  * So this is the local host, once, as a tested unit. It owns four things a
13
13
  * machine-level host owns and a library must not:
14
14
  *
15
- * 1. **Where the app's data lives** — `~/.app-managed/instances/<appId>`, honoring
16
- * `APP_MANAGED_HOME` through cwip's ONE resolver (never a bespoke `~/.<app>`).
15
+ * 1. **Where the app's data lives** — `<app-data-home>/instances/<appId>`, where
16
+ * the home is CONFIGURATION ({@link resolveAppDataHome}): an explicit
17
+ * argument, else `$APP_DATA_HOME`, else the OS convention. Never a bespoke
18
+ * `~/.<app>` directory, and never a folder named after one machine's owner.
17
19
  * 2. **Key custody.** The object-store URL signing key and the telemetry row
18
20
  * integrity key are minted once, persisted `0600`, and read back **as bytes**
19
21
  * — never as a string (V6 `key-material-as-string`; a hex string of a key
@@ -34,7 +36,6 @@
34
36
  import { Database } from 'bun:sqlite';
35
37
  import { generateKeyPairSync } from 'node:crypto';
36
38
  import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, type Stats, writeFileSync } from 'node:fs';
37
- import { homedir } from 'node:os';
38
39
  import path from 'node:path';
39
40
  import {
40
41
  assertArgon2idReady,
@@ -59,10 +60,10 @@ import type { DevServiceDeps, GuardServiceDeps } from './recipe';
59
60
  import {
60
61
  createTelemetryWriter,
61
62
  openTelemetryDatabase,
62
- resolveAppManagedHome,
63
63
  type TelemetryDatabase,
64
64
  type TelemetryWriter,
65
65
  } from 'cwip/telemetry';
66
+ import { resolveAppDataHome } from '../paths/appDataHome';
66
67
 
67
68
  /** Bytes in a minted key file. Matches cwip's `CC_KEY_BYTES`. */
68
69
  export const HOST_KEY_BYTES = 32;
@@ -71,21 +72,23 @@ export interface ResolveAppDataRootOptions {
71
72
  readonly appId: string;
72
73
  /** Explicit override (a `--data-root` flag, `CC_DATA_ROOT`). Wins outright. */
73
74
  readonly override?: string;
74
- /** Environment to read `APP_MANAGED_HOME` from. Injected by tests. */
75
+ /** Environment to read `APP_DATA_HOME` from. Injected by tests. */
75
76
  readonly env?: Record<string, string | undefined>;
76
77
  }
77
78
 
78
79
  /**
79
- * `<app-managed-home>/instances/<appId>` — the app's data root.
80
+ * `<app-data-home>/instances/<appId>` — the app's data root.
80
81
  *
81
82
  * A HOST function, not a library one: `openDomainHandles` still refuses to derive
82
- * a path, and this is the thing that hands it one.
83
+ * a path, and this is the thing that hands it one. The home underneath it is
84
+ * {@link resolveAppDataHome} — configuration, then the OS convention, and nothing
85
+ * else. A published package may not go looking for a directory it invented in
86
+ * somebody's home.
83
87
  */
84
88
  export function resolveAppDataRoot(options: ResolveAppDataRootOptions): string {
85
89
  const override = options.override?.trim();
86
90
  if (override) return path.resolve(override);
87
- const home = options.env ? resolveAppManagedHome(options.env) : resolveAppManagedHome();
88
- return path.join(home || path.join(homedir(), '.app-managed'), 'instances', options.appId);
91
+ return path.join(resolveAppDataHome({ env: options.env }), 'instances', options.appId);
89
92
  }
90
93
 
91
94
  /**
@@ -98,6 +98,7 @@ const shipAll = async (...list: readonly Node[]): Promise<void> => {
98
98
  }
99
99
  };
100
100
 
101
+ // SKIPPED unless CC_PG_URL names a throwaway Postgres — this suite's subject IS the engine. `bun run test:pg` supplies one.
101
102
  describe.skipIf(!URL_)('the shared meter against a real Postgres (04 item 4e)', () => {
102
103
  // 120s rather than Bun's 5s, for the reason `pooledControlStores.pg.test.ts`
103
104
  // records: this hook issues real DDL against a real engine, and on a shared CI
@@ -249,10 +249,10 @@ export function resolveManagedDomains(
249
249
 
250
250
  export interface OpenDomainHandlesOptions {
251
251
  /**
252
- * Where the per-domain SQLite files live (host-resolved, e.g.
253
- * `~/.app-managed/instances/<appId>/`). Required unless every needed domain
254
- * is supplied via `handles` — the library never invents a path from env
255
- * (handle-injection law).
252
+ * Where the per-domain SQLite files live (host-resolved, e.g. an
253
+ * `instances/<appId>/` directory under the host's own app-data root).
254
+ * Required unless every needed domain is supplied via `handles` — the
255
+ * library never invents a path from env (handle-injection law).
256
256
  */
257
257
  readonly root?: string;
258
258
  /**
@@ -61,6 +61,7 @@ const meterCount = async (): Promise<number> =>
61
61
  const auditCount = async (): Promise<number> =>
62
62
  Number(((await sql.unsafe(`SELECT COUNT(*)::int AS n FROM ${AUDIT_TRAIL_TABLE}`)) as Array<{ n: number }>)[0]?.n ?? -1);
63
63
 
64
+ // SKIPPED unless CC_PG_URL names a throwaway Postgres — this suite's subject IS the engine. `bun run test:pg` supplies one.
64
65
  describe.skipIf(!URL_)('the retention job against a real Postgres (01 §4)', () => {
65
66
  // 120s rather than Bun's 5s, for the reason the sibling pg suites record: this
66
67
  // hook issues real DDL, and on a shared runner a timeout surfaces as a
@@ -78,6 +78,7 @@ const doc = (id: string, title: string, body: string, tenantId = TENANT) => ({
78
78
  body,
79
79
  });
80
80
 
81
+ // SKIPPED unless CC_PG_URL names a throwaway Postgres — this suite's subject IS the engine. `bun run test:pg` supplies one.
81
82
  describe.skipIf(!ADMIN_URL)('createPgSearchProvider against a real Postgres (04 §3)', () => {
82
83
  // 120s for the same reason the control-plane suite gives: this hook drops and
83
84
  // rebuilds a whole role, database and schema, and on a shared CI runner a 5s
@@ -13,10 +13,14 @@ import { fsHlsMasterKey, fsMp4Key, fsPosterKey } from './types';
13
13
  // into its own store. Skips cleanly when the checkout or ffmpeg is absent.
14
14
  // Mirrors transcode.integration.spec.ts's harness.
15
15
 
16
- const BS_DIR = process.env.BINARY_SERVER_DIR ?? '/Users/curt/code/local/binary-server';
17
- const BS_PRESENT = existsSync(path.join(BS_DIR, 'src', 'index.ts'));
16
+ const BS_DIR = process.env.BINARY_SERVER_DIR ?? '';
17
+ const BS_PRESENT = BS_DIR !== '' && existsSync(path.join(BS_DIR, 'src', 'index.ts'));
18
18
  const FFMPEG_PRESENT = Bun.which('ffmpeg') !== null;
19
19
 
20
+ // SKIPPED until a real binary-server checkout is present: point BINARY_SERVER_DIR at one.
21
+ // There is deliberately no default — a published package must not go looking in one machine's
22
+ // directory layout — and `binary-server` has not been re-homed here, so this skips on every host today.
23
+ // ffmpeg must be on PATH too: the proof is that the REMOTE side runs real ffmpeg, not that the client posted a job.
20
24
  describe.skipIf(!BS_PRESENT || !FFMPEG_PRESENT)(
21
25
  'binaryServerProcessing → real binary-server (integration)',
22
26
  () => {
@@ -22,8 +22,8 @@ import type { MediaCtx } from './types';
22
22
  // chunk DIRECT to bs → bs assembles on the last chunk → complete registers the catalogue row over
23
23
  // the assembled bytes — and read the bytes back through the store. Skips cleanly when the local
24
24
  // binary-server checkout isn't present (CI / other machines).
25
- const BS_DIR = process.env.BINARY_SERVER_DIR ?? '/Users/curt/code/local/binary-server';
26
- const BS_PRESENT = existsSync(path.join(BS_DIR, 'src', 'index.ts'));
25
+ const BS_DIR = process.env.BINARY_SERVER_DIR ?? '';
26
+ const BS_PRESENT = BS_DIR !== '' && existsSync(path.join(BS_DIR, 'src', 'index.ts'));
27
27
  const ISSUER = 'https://demo.local';
28
28
  const APP_ID = 'demo';
29
29
  const CTX: MediaCtx = { userId: 'user-stub', tenantId: 'user-stub' };
@@ -38,6 +38,9 @@ const pem = (der: ArrayBuffer, label: string) =>
38
38
  .match(/.{1,64}/g) ?? []
39
39
  ).join('\n')}\n-----END ${label}-----\n`;
40
40
 
41
+ // SKIPPED until a real binary-server checkout is present: point BINARY_SERVER_DIR at one.
42
+ // There is deliberately no default — a published package must not go looking in one machine's
43
+ // directory layout — and `binary-server` has not been re-homed here, so this skips on every host today.
41
44
  describe.skipIf(!BS_PRESENT)('chunked upload → real binary-server (integration)', () => {
42
45
  let server: TestServer | null = null;
43
46
  let tmp = '';
@@ -26,8 +26,8 @@ import type { MediaCtx } from './types';
26
26
  // generated app uses in production — and pins the load-bearing property: the app origin sees
27
27
  // ONLY the small init/complete JSON calls, while every chunk PUTs DIRECT to binary-server.
28
28
  // Skips cleanly when the local binary-server checkout isn't present (CI / other machines).
29
- const BS_DIR = process.env.BINARY_SERVER_DIR ?? '/Users/curt/code/local/binary-server';
30
- const BS_PRESENT = existsSync(path.join(BS_DIR, 'src', 'index.ts'));
29
+ const BS_DIR = process.env.BINARY_SERVER_DIR ?? '';
30
+ const BS_PRESENT = BS_DIR !== '' && existsSync(path.join(BS_DIR, 'src', 'index.ts'));
31
31
  const ISSUER = 'https://demo.local';
32
32
  const APP_ID = 'demo';
33
33
  const CTX: MediaCtx = { userId: 'user-stub', tenantId: 'user-stub' };
@@ -42,6 +42,9 @@ const pem = (der: ArrayBuffer, label: string) =>
42
42
  .match(/.{1,64}/g) ?? []
43
43
  ).join('\n')}\n-----END ${label}-----\n`;
44
44
 
45
+ // SKIPPED until a real binary-server checkout is present: point BINARY_SERVER_DIR at one.
46
+ // There is deliberately no default — a published package must not go looking in one machine's
47
+ // directory layout — and `binary-server` has not been re-homed here, so this skips on every host today.
45
48
  describe.skipIf(!BS_PRESENT)('fileUploadClient chunked path → real binary-server (integration)', () => {
46
49
  let server: TestServer | null = null;
47
50
  let tmp = '';
@@ -75,6 +75,7 @@ async function heicBytes(): Promise<Uint8Array | null> {
75
75
  return bytes;
76
76
  }
77
77
 
78
+ // SKIPPED on a host without ffmpeg/ffprobe — it synthesizes and decodes real media. Runs by default wherever ffmpeg is installed.
78
79
  describe.skipIf(!haveFfmpeg)('photo display derivative (HEIC)', () => {
79
80
  let db: Database;
80
81
  let root: string;
@@ -44,6 +44,7 @@ async function makeHeic(dest: string): Promise<boolean> {
44
44
  return proc.exitCode === 0;
45
45
  }
46
46
 
47
+ // SKIPPED on a host without ffmpeg/ffprobe — it synthesizes and decodes real media. Runs by default wherever ffmpeg is installed.
47
48
  describe.skipIf(!haveFfmpeg)('ffmpegImageThumbnail', () => {
48
49
  test('decodes an HEVC/HEIC-style still into a width-capped JPEG', async () => {
49
50
  const root = await mkdtemp(path.join(tmpdir(), 'cb-imgthumb-'));
@@ -13,9 +13,12 @@ import { pickFreePort, startTestServer, type TestServer } from 'cwip/testing';
13
13
  // Contract: POST /api/transcode → { jobId }, GET /api/transcode/:jobId → { status, progress?, result? }.
14
14
  // Auth: x-internal-secret header must match process.env.INTERNAL_SECRET.
15
15
 
16
- const BS_DIR = process.env.BINARY_SERVER_DIR ?? '/Users/curt/code/local/binary-server';
17
- const BS_PRESENT = existsSync(path.join(BS_DIR, 'src', 'index.ts'));
16
+ const BS_DIR = process.env.BINARY_SERVER_DIR ?? '';
17
+ const BS_PRESENT = BS_DIR !== '' && existsSync(path.join(BS_DIR, 'src', 'index.ts'));
18
18
 
19
+ // SKIPPED until a real binary-server checkout is present: point BINARY_SERVER_DIR at one.
20
+ // There is deliberately no default — a published package must not go looking in one machine's
21
+ // directory layout — and `binary-server` has not been re-homed here, so this skips on every host today.
19
22
  describe.skipIf(!BS_PRESENT)('transcode API → real binary-server (integration)', () => {
20
23
  let port: number;
21
24
  let storeDir: string;
@@ -33,6 +33,7 @@ async function makeSource(dest: string, duration = 2): Promise<void> {
33
33
  }
34
34
 
35
35
  // posterOnly is the memory-constrained-host path: a poster + duration, but NO heavy HLS/re-encode.
36
+ // SKIPPED on a host without ffmpeg/ffprobe — it synthesizes and decodes real media. Runs by default wherever ffmpeg is installed.
36
37
  describe.skipIf(!haveFfmpeg)('processVideo posterOnly', () => {
37
38
  test('extracts a poster + duration, ready, no HLS', async () => {
38
39
  const root = await mkdtemp(path.join(tmpdir(), 'cb-poster-only-'));
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Clients parse exactly this shape, so there is no per-route error drift — and no
13
13
  * drift between a cwip-based server (which already emits it via `cwip/server`'s
14
- * `errorHandler`) and a cursedbelt/cursedshell one. The extra fields are additive:
14
+ * `errorHandler`) and a cursedshell one. The extra fields are additive:
15
15
  * a client that only reads `message`/`code`/`context` keeps working unchanged.
16
16
  *
17
17
  * `ApiError` is the ergonomic throwable: `throw new ApiError(404, 'not found')`.
@@ -0,0 +1,215 @@
1
+ /**
2
+ * 🔴 NO COMMENT, NO SKIP — and the doc that answers "what were they for" must stay true.
3
+ *
4
+ * ## What this cost, 2026-09-13
5
+ *
6
+ * `bun run verify` reported **5,132 pass / 82 skip / 0 fail**. Nobody could say what the 82
7
+ * were. Each had been written because something mattered and each had stopped running for a
8
+ * reason that was, by then, invisible: the gate condition was in the code
9
+ * (`describe.skipIf(!URL_)`), but *why that variable is unset on every host we own* was in
10
+ * nobody's head. A suite that carries a number like that quietly is a suite whose green means
11
+ * less than it says.
12
+ *
13
+ * Answering it took 16m 5s of agent time — the figure the runner's ledger recorded for the task,
14
+ * not an estimate — spent booting a throwaway Postgres, locating a binary-server checkout, and
15
+ * running each gated suite by hand to learn whether it still passes. All 82 turned out to be
16
+ * healthy, environment-gated proofs. That is the good outcome, and it is exactly why the next
17
+ * person must not have to re-derive it: the cost was never the fixing, it was the *finding
18
+ * out*.
19
+ *
20
+ * ## So this is a check, not a paragraph
21
+ *
22
+ * Two assertions, both of which fail the moment the record stops matching the code:
23
+ *
24
+ * 1. **Every skip site in `src` carries its reason in the comment directly above it.** A new
25
+ * `describe.skipIf` with no comment is a red gate, at the moment it is written, by the
26
+ * person who knows the answer — which is the only moment the answer is cheap.
27
+ * 2. **`docs/skipped-tests.md` names exactly the files that have one.** A skip that is
28
+ * deleted or added without updating the record reds too, so the doc cannot rot into the
29
+ * confident-but-wrong state that makes a doc worse than nothing.
30
+ *
31
+ * It deliberately does NOT assert a skip COUNT. The counts move with the host — ffmpeg
32
+ * installed or not, `CC_PG_URL` set or not — and a check that reds because someone installed
33
+ * `sharp` teaches people to delete the check.
34
+ */
35
+ import { describe, expect, test } from 'bun:test';
36
+ import { readdirSync, readFileSync } from 'node:fs';
37
+ import path from 'node:path';
38
+ import { fileURLToPath } from 'node:url';
39
+
40
+ const SRC = fileURLToPath(new URL('.', import.meta.url));
41
+ const REPO = path.resolve(SRC, '..');
42
+ const SELF = 'src/skippedTestsAreAnswered.spec.ts';
43
+ const DOC = 'docs/skipped-tests.md';
44
+
45
+ /**
46
+ * A skip site: `describe.skip`, `.todo`, `.failing`, `.skipIf`, `.todoIf` on any of bun's three
47
+ * entry points, plus the jasmine-era `xit(` / `xdescribe(`.
48
+ *
49
+ * Anchored on the entry point so that ordinary identifiers containing "skip" — `skipDirs`,
50
+ * `skipToken`, `skipKdfReadinessGate`, all of which live in this package — are not sites.
51
+ */
52
+ const SKIP_SITE = /\b(?:describe|it|test)\s*\.\s*(?:skip|todo|failing|skipIf|todoIf)\b|\bx(?:it|describe)\s*\(/;
53
+
54
+ /** A comment line, in either style, as it appears immediately above a skip site. */
55
+ const COMMENT_LINE = /^\s*(?:\/\/|\/\*|\*)/;
56
+
57
+ export interface SkipSite {
58
+ /** 1-indexed, so a failure message is clickable. */
59
+ readonly line: number;
60
+ readonly text: string;
61
+ /** The contiguous comment block directly above, with no blank line between it and the site. */
62
+ readonly reason: string;
63
+ }
64
+
65
+ /**
66
+ * Every skip site in one file's source, each carrying whatever comment sits directly above it.
67
+ *
68
+ * "Directly above" is strict on purpose: a blank line between the comment and the site ends the
69
+ * block. The failure this guards against is a skip drifting away from the explanation that was
70
+ * once next to it, and a blank line is exactly how that drift starts.
71
+ */
72
+ export const findSkipSites = (source: string): SkipSite[] => {
73
+ const lines = source.split('\n');
74
+ const sites: SkipSite[] = [];
75
+ for (let i = 0; i < lines.length; i += 1) {
76
+ const text = lines[i] as string;
77
+ if (!SKIP_SITE.test(text)) continue;
78
+ const above: string[] = [];
79
+ for (let j = i - 1; j >= 0; j -= 1) {
80
+ const prev = lines[j] as string;
81
+ if (!COMMENT_LINE.test(prev)) break;
82
+ above.unshift(prev);
83
+ }
84
+ sites.push({ line: i + 1, text: text.trim(), reason: above.join('\n') });
85
+ }
86
+ return sites;
87
+ };
88
+
89
+ /** A reason has to be ABOUT the skip. Any comment at all would pass otherwise. */
90
+ export const isAnswered = (site: SkipSite): boolean => /skip/i.test(site.reason);
91
+
92
+ /** Every `src` file that contains at least one skip site, repo-relative and sorted. */
93
+ const scanSrc = (): Map<string, SkipSite[]> => {
94
+ const found = new Map<string, SkipSite[]>();
95
+ for (const entry of readdirSync(SRC, { recursive: true })) {
96
+ const name = String(entry);
97
+ if (!/\.tsx?$/.test(name)) continue;
98
+ const rel = `src/${name.split(path.sep).join('/')}`;
99
+ if (rel === SELF) continue; // the checker names the patterns it bans, so it cannot scan itself
100
+ const sites = findSkipSites(readFileSync(path.join(SRC, name), 'utf8'));
101
+ if (sites.length > 0) found.set(rel, sites);
102
+ }
103
+ return new Map([...found].sort(([a], [b]) => a.localeCompare(b)));
104
+ };
105
+
106
+ /**
107
+ * The suites `docs/skipped-tests.md` claims to cover.
108
+ *
109
+ * Only backticked paths in a TABLE ROW count, so the prose above and below the table stays free
110
+ * to mention any file it likes — including this one.
111
+ */
112
+ const documentedSuites = async (): Promise<Set<string>> => {
113
+ const doc = await Bun.file(path.join(REPO, DOC)).text();
114
+ const rows = doc.split('\n').filter((l) => l.trimStart().startsWith('|'));
115
+ const named = new Set<string>();
116
+ for (const row of rows) for (const m of row.matchAll(/`(src\/[^`]+\.tsx?)`/g)) named.add(m[1] as string);
117
+ return named;
118
+ };
119
+
120
+ describe('every skip in src answers for itself', () => {
121
+ test('each skip site carries its reason in the comment directly above it', () => {
122
+ const unanswered: string[] = [];
123
+ for (const [file, sites] of scanSrc())
124
+ for (const site of sites) if (!isAnswered(site)) unanswered.push(`${file}:${site.line} ${site.text}`);
125
+
126
+ expect(
127
+ unanswered,
128
+ `A skipped test with no stated reason is a question nobody can answer later — answering the 82 already here\n` +
129
+ `cost a task of its own on 2026-09-13 (16m 5s, per the runner's ledger). Put one line directly above the\n` +
130
+ `skip saying what it is WAITING FOR (a service, a fixture, a\n` +
131
+ `browser, a decision), mentioning the word "skip", and add a row to ${DOC}. If it passes today, unskip it\n` +
132
+ `instead. Never delete a test to make the number fall.\n\nUnanswered:\n ${unanswered.join('\n ')}`,
133
+ ).toEqual([]);
134
+ });
135
+ });
136
+
137
+ describe(`${DOC} matches the suite`, () => {
138
+ test('it names every file that carries a skip', async () => {
139
+ const documented = await documentedSuites();
140
+ const missing = [...scanSrc().keys()].filter((f) => !documented.has(f));
141
+ expect(
142
+ missing,
143
+ `These files gained a skip that ${DOC} does not mention. Add a table row: what it waits for, how to run it,\n` +
144
+ `and when it was last seen green.\n\n ${missing.join('\n ')}`,
145
+ ).toEqual([]);
146
+ });
147
+
148
+ test('it names no file that has stopped carrying one', async () => {
149
+ const live = scanSrc();
150
+ const stale = [...(await documentedSuites())].filter((f) => !live.has(f));
151
+ expect(
152
+ stale,
153
+ `${DOC} still lists these as skipped, but they no longer contain a skip site. Good news — delete the rows\n` +
154
+ `(and move the count) so the record stops claiming something that is no longer true.\n\n ${stale.join('\n ')}`,
155
+ ).toEqual([]);
156
+ });
157
+ });
158
+
159
+ /**
160
+ * The detector's own failure path. A gate nobody has seen RED is a gate nobody knows works, and
161
+ * this one's whole value is that it fires on the day a skip is introduced.
162
+ */
163
+ describe('the detector itself', () => {
164
+ test('an uncommented skip is a finding', () => {
165
+ const sites = findSkipSites(["describe.skipIf(!URL_)('x', () => {", '});'].join('\n'));
166
+ expect(sites).toHaveLength(1);
167
+ expect(isAnswered(sites[0] as SkipSite)).toBe(false);
168
+ });
169
+
170
+ test('a skip whose comment explains the skip is not', () => {
171
+ const sites = findSkipSites(
172
+ ['// SKIPPED unless CC_PG_URL names a real Postgres.', "describe.skipIf(!URL_)('x', () => {", '});'].join('\n'),
173
+ );
174
+ expect(isAnswered(sites[0] as SkipSite)).toBe(true);
175
+ });
176
+
177
+ test('a comment about something else does NOT answer for the skip', () => {
178
+ const sites = findSkipSites(
179
+ ['// posterOnly is the memory-constrained-host path.', "describe.skipIf(!ffmpeg)('x', () => {", '});'].join('\n'),
180
+ );
181
+ expect(isAnswered(sites[0] as SkipSite)).toBe(false);
182
+ });
183
+
184
+ test('a blank line between the comment and the skip breaks the block', () => {
185
+ const sites = findSkipSites(
186
+ ['// SKIPPED unless CC_PG_URL is set.', '', "describe.skipIf(!URL_)('x', () => {", '});'].join('\n'),
187
+ );
188
+ expect(sites[0]?.reason).toBe('');
189
+ expect(isAnswered(sites[0] as SkipSite)).toBe(false);
190
+ });
191
+
192
+ test('a JSDoc block above the skip counts as the reason', () => {
193
+ const sites = findSkipSites(
194
+ ['/**', ' * SKIPPED until the browser harness exists.', ' */', "it.skip('x', () => {});"].join('\n'),
195
+ );
196
+ expect(isAnswered(sites[0] as SkipSite)).toBe(true);
197
+ });
198
+
199
+ test('it finds the other spellings too', () => {
200
+ expect(findSkipSites("it.todo('later');")).toHaveLength(1);
201
+ expect(findSkipSites("test.failing('known bad');")).toHaveLength(1);
202
+ expect(findSkipSites("xit('old style', () => {});")).toHaveLength(1);
203
+ expect(findSkipSites("xdescribe('old style', () => {});")).toHaveLength(1);
204
+ });
205
+
206
+ test('an identifier that merely contains "skip" is not a skip site', () => {
207
+ expect(findSkipSites('const skip = new Set(opts.skipDirs ?? []);')).toEqual([]);
208
+ expect(findSkipSites('if (options.skipKdfReadinessGate !== true) assertArgon2idReady();')).toEqual([]);
209
+ expect(findSkipSites('const q = useQuery({ queryKey: k, initialPageParam: skipToken });')).toEqual([]);
210
+ });
211
+
212
+ test('this package has skip sites to find — a detector that finds nothing proves nothing', () => {
213
+ expect(scanSrc().size).toBeGreaterThan(0);
214
+ });
215
+ });