@revola-ai/video-craft 0.2.1

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 (340) hide show
  1. package/README.md +56 -0
  2. package/dist/anchors.js +69 -0
  3. package/dist/corpus.js +91 -0
  4. package/dist/projectDoc.js +83 -0
  5. package/dist/projectDocSync.js +39 -0
  6. package/dist/projectMeta.js +37 -0
  7. package/dist/provenance.js +41 -0
  8. package/dist/radar-check-ids.json +34 -0
  9. package/dist/registry.js +307 -0
  10. package/dist/rules/animatedBarChartTightBox.js +15 -0
  11. package/dist/rules/animatedBarChartWhenNotToUse.js +15 -0
  12. package/dist/rules/animatedBarChartWhenToUse.js +15 -0
  13. package/dist/rules/animatedLineChartWhenNotToUse.js +15 -0
  14. package/dist/rules/animatedLineChartWhenToUse.js +15 -0
  15. package/dist/rules/approvedSfxPaletteOnly.js +15 -0
  16. package/dist/rules/atmosphereGradientsFadeAtBothEnds.js +15 -0
  17. package/dist/rules/audioIsTheClock.js +16 -0
  18. package/dist/rules/beatsDeriveFromTheirOwnSequence.js +15 -0
  19. package/dist/rules/bestSceneSetsTheBar.js +15 -0
  20. package/dist/rules/bumpBeforeRefreeze.js +15 -0
  21. package/dist/rules/cameraIsTheNarrator.js +15 -0
  22. package/dist/rules/checkPinBeforeShip.js +16 -0
  23. package/dist/rules/coldViewerClarity.js +15 -0
  24. package/dist/rules/commitOrCutEffects.js +29 -0
  25. package/dist/rules/convertFramesAcrossClockBoundary.js +15 -0
  26. package/dist/rules/crossCutElementsLiveInTheHudLayer.js +15 -0
  27. package/dist/rules/cursorClicksRealControls.js +15 -0
  28. package/dist/rules/cutOnRealAudioPauses.js +15 -0
  29. package/dist/rules/darkButNeverDim.js +15 -0
  30. package/dist/rules/dataRadarTagsDeclared.js +193 -0
  31. package/dist/rules/declareAVerticalZoneMap.js +15 -0
  32. package/dist/rules/deleteRejectedRigsCompletely.js +15 -0
  33. package/dist/rules/deriveSeamsDontMeasure.js +17 -0
  34. package/dist/rules/deterministicSceneSource.js +65 -0
  35. package/dist/rules/diegeticSoundForOnscreenActions.js +15 -0
  36. package/dist/rules/distinctTransitionPerBeat.js +15 -0
  37. package/dist/rules/downloadOrDrawRichAssets.js +15 -0
  38. package/dist/rules/elementOnscreenForItsVoSentence.js +17 -0
  39. package/dist/rules/emitBuildNotes.js +15 -0
  40. package/dist/rules/energyFromTimingNotPartCount.js +15 -0
  41. package/dist/rules/evidenceBeforeClaimingFixed.js +15 -0
  42. package/dist/rules/exactPeerLockstep.js +15 -0
  43. package/dist/rules/firstPassIsADraft.js +15 -0
  44. package/dist/rules/fixCrowdingByRebandingNotNudging.js +15 -0
  45. package/dist/rules/fixesPreserveApprovedElements.js +15 -0
  46. package/dist/rules/floatingNotBoxed.js +15 -0
  47. package/dist/rules/focusBeatsRecedeTheContext.js +15 -0
  48. package/dist/rules/fontVarsBrandRemocn.js +15 -0
  49. package/dist/rules/geometricSeamsNotCrossfades.js +23 -0
  50. package/dist/rules/geometrySidecarExportsTyped.js +36 -0
  51. package/dist/rules/glowIsAFocalAccent.js +22 -0
  52. package/dist/rules/heroFillsTheFrame.js +17 -0
  53. package/dist/rules/htmlMasksForAnimatedCounters.js +15 -0
  54. package/dist/rules/impactStackOnPayoffs.js +15 -0
  55. package/dist/rules/interactiveTargetsAreDeclaredData.js +15 -0
  56. package/dist/rules/interpolateLiteralKeysMonotonic.js +79 -0
  57. package/dist/rules/latenessIsStructuralOverlapTheBeats.js +15 -0
  58. package/dist/rules/lessTextMoreVisualizations.js +15 -0
  59. package/dist/rules/liveLinkDuplicateReactAlias.js +15 -0
  60. package/dist/rules/make2dElements3d.js +15 -0
  61. package/dist/rules/masterMixLoudnessTarget.js +17 -0
  62. package/dist/rules/measureAlignmentDontEyeball.js +15 -0
  63. package/dist/rules/motionCarriesWeightAndMeaning.js +15 -0
  64. package/dist/rules/motionDensityFloor.js +15 -0
  65. package/dist/rules/neverEditTierBVendored.js +15 -0
  66. package/dist/rules/neverRestateDerivedFrameNumbersInComments.js +15 -0
  67. package/dist/rules/noAiGradientLook.js +15 -0
  68. package/dist/rules/noColoredFlashToHideACut.js +22 -0
  69. package/dist/rules/noDoubleFrameShift.js +126 -0
  70. package/dist/rules/noDuplicateMotionPrimitives.js +15 -0
  71. package/dist/rules/noLinearMotion.js +22 -0
  72. package/dist/rules/noNestedSvgFilters.js +93 -0
  73. package/dist/rules/noRepeatedAssetAcrossShots.js +15 -0
  74. package/dist/rules/noShorthandWithUndefinedLonghand.js +93 -0
  75. package/dist/rules/noStackedFadesAtACut.js +24 -0
  76. package/dist/rules/noStaticHolds.js +17 -0
  77. package/dist/rules/occlusionVisibleElements.js +17 -0
  78. package/dist/rules/oneContinuousVoTrack.js +15 -0
  79. package/dist/rules/onePunchPerMomentClass.js +15 -0
  80. package/dist/rules/oneRenderPerRound.js +15 -0
  81. package/dist/rules/openStaticAfterAHardCut.js +22 -0
  82. package/dist/rules/openingsAndClosingsCarryMore.js +15 -0
  83. package/dist/rules/persistentDeviceFrames.js +15 -0
  84. package/dist/rules/pixelDiffAnEmptyBandFirst.js +15 -0
  85. package/dist/rules/planIsPublishedNotGating.js +15 -0
  86. package/dist/rules/poweredByRevolaWatermark.js +15 -0
  87. package/dist/rules/predrawContentPresentAtTheCut.js +17 -0
  88. package/dist/rules/premiumSurfacesNotFlatBorders.js +15 -0
  89. package/dist/rules/radarDispositionsAreHumanOnly.js +17 -0
  90. package/dist/rules/realAssetsNotPlaceholders.js +15 -0
  91. package/dist/rules/rebuildUiFromReconNotScreenshots.js +15 -0
  92. package/dist/rules/reconStrandsRunInParallel.js +15 -0
  93. package/dist/rules/registryBeforeHandrolling.js +15 -0
  94. package/dist/rules/remapRateEndpointFormula.js +15 -0
  95. package/dist/rules/remocnContentTailwindChrome.js +15 -0
  96. package/dist/rules/retimeOnlyViaPlaybackOrDesignTokens.js +15 -0
  97. package/dist/rules/reviewTheRenderByFrameSweep.js +15 -0
  98. package/dist/rules/rollingNumberBoundedSequence.js +17 -0
  99. package/dist/rules/rollingNumberSequenceLayoutNone.js +16 -0
  100. package/dist/rules/rollingNumberTightBoxAlignment.js +15 -0
  101. package/dist/rules/rollingNumberWhenNotToUse.js +17 -0
  102. package/dist/rules/rollingNumberWhenToUse.js +17 -0
  103. package/dist/rules/sameFamilySameProject.js +15 -0
  104. package/dist/rules/sampleBrandFromProduct.js +15 -0
  105. package/dist/rules/sampleVelocityFromPreviousFramePosition.js +15 -0
  106. package/dist/rules/sceneRootTagDeclared.js +41 -0
  107. package/dist/rules/scrubDemoDataToGenericRoles.js +15 -0
  108. package/dist/rules/selfReviewThePlanForGaps.js +15 -0
  109. package/dist/rules/sourceArchivedBeforeBrief.js +17 -0
  110. package/dist/rules/statisticsSelfExplanatory.js +15 -0
  111. package/dist/rules/stopsAsRelativeSpacing.js +15 -0
  112. package/dist/rules/theWholeCanvasWorks.js +15 -0
  113. package/dist/rules/themePerSection.js +22 -0
  114. package/dist/rules/thesisDeclaredInBrief.js +17 -0
  115. package/dist/rules/tierARequiresPropUnreachableEdit.js +15 -0
  116. package/dist/rules/tinyBodyCopyAsRuledLines.js +15 -0
  117. package/dist/rules/titlesPinnedOutsideCameraPush.js +15 -0
  118. package/dist/rules/tokensNotRawHexes.js +60 -0
  119. package/dist/rules/typeTokenDefaultedParamsAsString.js +15 -0
  120. package/dist/rules/varyKitChoreographyAcrossSections.js +15 -0
  121. package/dist/rules/varyTheVisualizationGrammar.js +15 -0
  122. package/dist/rules/verifyCheapRenderDear.js +15 -0
  123. package/dist/rules/voAddressesTheViewer.js +15 -0
  124. package/dist/rules/voIsAPerformance.js +15 -0
  125. package/dist/rules/voScriptLocksSpokenWords.js +15 -0
  126. package/dist/rules/wrappersPreserveChildGeometry.js +15 -0
  127. package/dist/sourceCheck.js +47 -0
  128. package/dist/sourceCitations.js +68 -0
  129. package/dist/stageProjection.js +69 -0
  130. package/dist/stages.js +163 -0
  131. package/dist/testSupport.js +6 -0
  132. package/dist/types.js +0 -0
  133. package/dist/variants.js +8 -0
  134. package/dist/waiverProjection.js +20 -0
  135. package/package.json +32 -0
  136. package/src/anchors.test.ts +119 -0
  137. package/src/anchors.ts +110 -0
  138. package/src/corpus.test.ts +96 -0
  139. package/src/corpus.ts +149 -0
  140. package/src/corpusProject.test.ts +103 -0
  141. package/src/creativeEdge.test.ts +58 -0
  142. package/src/distBuild.test.ts +86 -0
  143. package/src/docStatus.test.ts +81 -0
  144. package/src/drift.test.ts +124 -0
  145. package/src/fixtures/data-radar-dynamic/Branches.tsx +14 -0
  146. package/src/fixtures/data-radar-dynamic/plan.fixture.yaml +16 -0
  147. package/src/fixtures/data-radar-forwarded/Scene.tsx +19 -0
  148. package/src/fixtures/data-radar-forwarded/plan.fixture.yaml +13 -0
  149. package/src/fixtures/data-radar-opaque/Scene.tsx +15 -0
  150. package/src/fixtures/data-radar-opaque/plan.fixture.yaml +10 -0
  151. package/src/fixtures/data-radar-tags/SceneClean.tsx +10 -0
  152. package/src/fixtures/data-radar-tags/SceneNullBinding.tsx +12 -0
  153. package/src/fixtures/data-radar-tags/SceneWithGap.tsx +11 -0
  154. package/src/fixtures/data-radar-tags/plan.fixture.yaml +29 -0
  155. package/src/fixtures/deterministic-scene.tsx +15 -0
  156. package/src/fixtures/double-shift/aliased.tsx +13 -0
  157. package/src/fixtures/double-shift/assigned.tsx +13 -0
  158. package/src/fixtures/double-shift/clean.tsx +19 -0
  159. package/src/fixtures/double-shift/destructured.tsx +12 -0
  160. package/src/fixtures/double-shift/elementAccess.tsx +12 -0
  161. package/src/fixtures/double-shift/layout.ts +24 -0
  162. package/src/fixtures/double-shift/mechanism-prefix.tsx.txt +458 -0
  163. package/src/fixtures/double-shift/wrapped.tsx +15 -0
  164. package/src/fixtures/geometry-sidecar-missing-export.ts +10 -0
  165. package/src/fixtures/geometry-sidecar-missing-type.ts +7 -0
  166. package/src/fixtures/geometry-sidecar-valid.ts +6 -0
  167. package/src/fixtures/interpolate-ascending.tsx +6 -0
  168. package/src/fixtures/interpolate-descending.tsx +8 -0
  169. package/src/fixtures/interpolate-identifier-keys.tsx +9 -0
  170. package/src/fixtures/nested-filters-broken.tsx +11 -0
  171. package/src/fixtures/nested-filters-fixed.tsx +8 -0
  172. package/src/fixtures/nested-filters-html-wrapper.tsx +14 -0
  173. package/src/fixtures/nested-filters-html.tsx +7 -0
  174. package/src/fixtures/nested-filters-siblings.tsx +12 -0
  175. package/src/fixtures/nondeterministic-scene.tsx +14 -0
  176. package/src/fixtures/nondeterministic-variants.tsx +16 -0
  177. package/src/fixtures/raw-hex-scene.tsx +10 -0
  178. package/src/fixtures/scene-root-declared/SceneHook.tsx +9 -0
  179. package/src/fixtures/scene-root-declared/plan.fixture.yaml +10 -0
  180. package/src/fixtures/scene-root-missing/SceneHook.tsx +11 -0
  181. package/src/fixtures/scene-root-missing/plan.fixture.yaml +10 -0
  182. package/src/fixtures/scene-root-no-names/SceneHook.tsx +6 -0
  183. package/src/fixtures/scene-root-no-names/plan.fixture.yaml +6 -0
  184. package/src/fixtures/scene-root-shell/SceneHook.tsx +8 -0
  185. package/src/fixtures/scene-root-shell/Shell.tsx +9 -0
  186. package/src/fixtures/scene-root-shell/plan.fixture.yaml +10 -0
  187. package/src/fixtures/shorthand-undefined-clean.tsx +23 -0
  188. package/src/fixtures/shorthand-undefined-longhand.tsx +17 -0
  189. package/src/fixtures/token-scene.tsx +9 -0
  190. package/src/includeCoverage.test.ts +176 -0
  191. package/src/learnedFrom.test.ts +32 -0
  192. package/src/projectDoc.test.ts +230 -0
  193. package/src/projectDoc.ts +152 -0
  194. package/src/projectDocSync.test.ts +152 -0
  195. package/src/projectDocSync.ts +79 -0
  196. package/src/projectMeta.test.ts +75 -0
  197. package/src/projectMeta.ts +53 -0
  198. package/src/provenance.ts +85 -0
  199. package/src/radar-check-ids.json +34 -0
  200. package/src/registry.test.ts +207 -0
  201. package/src/registry.ts +352 -0
  202. package/src/rules/animatedBarChartTightBox.ts +14 -0
  203. package/src/rules/animatedBarChartWhenNotToUse.ts +14 -0
  204. package/src/rules/animatedBarChartWhenToUse.ts +14 -0
  205. package/src/rules/animatedLineChartWhenNotToUse.ts +14 -0
  206. package/src/rules/animatedLineChartWhenToUse.ts +14 -0
  207. package/src/rules/approvedSfxPaletteOnly.ts +23 -0
  208. package/src/rules/atmosphereGradientsFadeAtBothEnds.ts +21 -0
  209. package/src/rules/audioIsTheClock.ts +22 -0
  210. package/src/rules/beatsDeriveFromTheirOwnSequence.ts +21 -0
  211. package/src/rules/bestSceneSetsTheBar.ts +21 -0
  212. package/src/rules/bumpBeforeRefreeze.ts +20 -0
  213. package/src/rules/cameraIsTheNarrator.ts +21 -0
  214. package/src/rules/checkPinBeforeShip.ts +22 -0
  215. package/src/rules/coldViewerClarity.ts +21 -0
  216. package/src/rules/commitOrCutEffects.ts +36 -0
  217. package/src/rules/convertFramesAcrossClockBoundary.ts +19 -0
  218. package/src/rules/crossCutElementsLiveInTheHudLayer.ts +21 -0
  219. package/src/rules/cursorClicksRealControls.ts +22 -0
  220. package/src/rules/cutOnRealAudioPauses.ts +20 -0
  221. package/src/rules/darkButNeverDim.ts +21 -0
  222. package/src/rules/dataRadarTagsDeclared.test.ts +60 -0
  223. package/src/rules/dataRadarTagsDeclared.ts +341 -0
  224. package/src/rules/declareAVerticalZoneMap.ts +19 -0
  225. package/src/rules/deleteRejectedRigsCompletely.ts +19 -0
  226. package/src/rules/deriveSeamsDontMeasure.ts +23 -0
  227. package/src/rules/deterministicSceneSource.test.ts +58 -0
  228. package/src/rules/deterministicSceneSource.ts +82 -0
  229. package/src/rules/diegeticSoundForOnscreenActions.ts +21 -0
  230. package/src/rules/distinctTransitionPerBeat.ts +21 -0
  231. package/src/rules/downloadOrDrawRichAssets.ts +22 -0
  232. package/src/rules/elementOnscreenForItsVoSentence.ts +25 -0
  233. package/src/rules/emitBuildNotes.ts +19 -0
  234. package/src/rules/energyFromTimingNotPartCount.ts +20 -0
  235. package/src/rules/evidenceBeforeClaimingFixed.ts +23 -0
  236. package/src/rules/exactPeerLockstep.ts +19 -0
  237. package/src/rules/firstPassIsADraft.ts +20 -0
  238. package/src/rules/fixCrowdingByRebandingNotNudging.ts +20 -0
  239. package/src/rules/fixesPreserveApprovedElements.ts +24 -0
  240. package/src/rules/floatingNotBoxed.ts +21 -0
  241. package/src/rules/focusBeatsRecedeTheContext.ts +20 -0
  242. package/src/rules/fontVarsBrandRemocn.ts +20 -0
  243. package/src/rules/geometricSeamsNotCrossfades.ts +28 -0
  244. package/src/rules/geometrySidecarExportsTyped.test.ts +37 -0
  245. package/src/rules/geometrySidecarExportsTyped.ts +59 -0
  246. package/src/rules/glowIsAFocalAccent.ts +28 -0
  247. package/src/rules/heroFillsTheFrame.ts +24 -0
  248. package/src/rules/htmlMasksForAnimatedCounters.ts +21 -0
  249. package/src/rules/impactStackOnPayoffs.ts +26 -0
  250. package/src/rules/interactiveTargetsAreDeclaredData.ts +21 -0
  251. package/src/rules/interpolateLiteralKeysMonotonic.test.ts +49 -0
  252. package/src/rules/interpolateLiteralKeysMonotonic.ts +98 -0
  253. package/src/rules/latenessIsStructuralOverlapTheBeats.ts +20 -0
  254. package/src/rules/lessTextMoreVisualizations.ts +22 -0
  255. package/src/rules/liveLinkDuplicateReactAlias.ts +22 -0
  256. package/src/rules/make2dElements3d.ts +21 -0
  257. package/src/rules/masterMixLoudnessTarget.ts +22 -0
  258. package/src/rules/measureAlignmentDontEyeball.ts +20 -0
  259. package/src/rules/motionCarriesWeightAndMeaning.ts +21 -0
  260. package/src/rules/motionDensityFloor.ts +20 -0
  261. package/src/rules/neverEditTierBVendored.ts +20 -0
  262. package/src/rules/neverRestateDerivedFrameNumbersInComments.ts +20 -0
  263. package/src/rules/noAiGradientLook.ts +22 -0
  264. package/src/rules/noColoredFlashToHideACut.ts +29 -0
  265. package/src/rules/noDoubleFrameShift.test.ts +95 -0
  266. package/src/rules/noDoubleFrameShift.ts +193 -0
  267. package/src/rules/noDuplicateMotionPrimitives.ts +19 -0
  268. package/src/rules/noLinearMotion.ts +29 -0
  269. package/src/rules/noNestedSvgFilters.test.ts +47 -0
  270. package/src/rules/noNestedSvgFilters.ts +138 -0
  271. package/src/rules/noRepeatedAssetAcrossShots.ts +19 -0
  272. package/src/rules/noShorthandWithUndefinedLonghand.test.ts +35 -0
  273. package/src/rules/noShorthandWithUndefinedLonghand.ts +140 -0
  274. package/src/rules/noStackedFadesAtACut.ts +30 -0
  275. package/src/rules/noStaticHolds.ts +24 -0
  276. package/src/rules/occlusionVisibleElements.ts +26 -0
  277. package/src/rules/oneContinuousVoTrack.ts +20 -0
  278. package/src/rules/onePunchPerMomentClass.ts +20 -0
  279. package/src/rules/oneRenderPerRound.ts +46 -0
  280. package/src/rules/openStaticAfterAHardCut.ts +29 -0
  281. package/src/rules/openingsAndClosingsCarryMore.ts +21 -0
  282. package/src/rules/persistentDeviceFrames.ts +20 -0
  283. package/src/rules/pixelDiffAnEmptyBandFirst.ts +20 -0
  284. package/src/rules/planIsPublishedNotGating.ts +32 -0
  285. package/src/rules/poweredByRevolaWatermark.ts +19 -0
  286. package/src/rules/predrawContentPresentAtTheCut.ts +21 -0
  287. package/src/rules/premiumSurfacesNotFlatBorders.ts +20 -0
  288. package/src/rules/radarDispositionsAreHumanOnly.ts +28 -0
  289. package/src/rules/realAssetsNotPlaceholders.ts +21 -0
  290. package/src/rules/rebuildUiFromReconNotScreenshots.ts +21 -0
  291. package/src/rules/reconStrandsRunInParallel.ts +63 -0
  292. package/src/rules/registryBeforeHandrolling.ts +20 -0
  293. package/src/rules/remapRateEndpointFormula.ts +19 -0
  294. package/src/rules/remocnContentTailwindChrome.ts +19 -0
  295. package/src/rules/retimeOnlyViaPlaybackOrDesignTokens.ts +18 -0
  296. package/src/rules/reviewTheRenderByFrameSweep.ts +23 -0
  297. package/src/rules/rollingNumberBoundedSequence.ts +21 -0
  298. package/src/rules/rollingNumberSequenceLayoutNone.ts +22 -0
  299. package/src/rules/rollingNumberTightBoxAlignment.ts +19 -0
  300. package/src/rules/rollingNumberWhenNotToUse.ts +24 -0
  301. package/src/rules/rollingNumberWhenToUse.ts +23 -0
  302. package/src/rules/sameFamilySameProject.ts +20 -0
  303. package/src/rules/sampleBrandFromProduct.ts +19 -0
  304. package/src/rules/sampleVelocityFromPreviousFramePosition.ts +21 -0
  305. package/src/rules/sceneRootTagDeclared.test.ts +43 -0
  306. package/src/rules/sceneRootTagDeclared.ts +78 -0
  307. package/src/rules/scrubDemoDataToGenericRoles.ts +19 -0
  308. package/src/rules/selfReviewThePlanForGaps.ts +47 -0
  309. package/src/rules/sourceArchivedBeforeBrief.ts +24 -0
  310. package/src/rules/statisticsSelfExplanatory.ts +18 -0
  311. package/src/rules/stopsAsRelativeSpacing.ts +21 -0
  312. package/src/rules/theWholeCanvasWorks.ts +21 -0
  313. package/src/rules/themePerSection.ts +28 -0
  314. package/src/rules/thesisDeclaredInBrief.ts +25 -0
  315. package/src/rules/tierARequiresPropUnreachableEdit.ts +20 -0
  316. package/src/rules/tinyBodyCopyAsRuledLines.ts +19 -0
  317. package/src/rules/titlesPinnedOutsideCameraPush.ts +22 -0
  318. package/src/rules/tokensNotRawHexes.test.ts +51 -0
  319. package/src/rules/tokensNotRawHexes.ts +89 -0
  320. package/src/rules/typeTokenDefaultedParamsAsString.ts +21 -0
  321. package/src/rules/varyKitChoreographyAcrossSections.ts +21 -0
  322. package/src/rules/varyTheVisualizationGrammar.ts +22 -0
  323. package/src/rules/verifyCheapRenderDear.ts +18 -0
  324. package/src/rules/voAddressesTheViewer.ts +18 -0
  325. package/src/rules/voIsAPerformance.ts +21 -0
  326. package/src/rules/voScriptLocksSpokenWords.ts +21 -0
  327. package/src/rules/wrappersPreserveChildGeometry.ts +22 -0
  328. package/src/sourceCheck.test.ts +50 -0
  329. package/src/sourceCheck.ts +55 -0
  330. package/src/sourceCitations.test.ts +747 -0
  331. package/src/sourceCitations.ts +217 -0
  332. package/src/stageProjection.ts +112 -0
  333. package/src/stages.test.ts +68 -0
  334. package/src/stages.ts +207 -0
  335. package/src/testSupport.ts +16 -0
  336. package/src/types.ts +181 -0
  337. package/src/variants.test.ts +24 -0
  338. package/src/variants.ts +13 -0
  339. package/src/waiverProjection.test.ts +59 -0
  340. package/src/waiverProjection.ts +45 -0
package/src/types.ts ADDED
@@ -0,0 +1,181 @@
1
+ import type { SourceFile } from "ts-morph";
2
+
3
+ /** A live code location a prose rule asserts something about. */
4
+ export type CodeAnchor = {
5
+ /** Repo-relative POSIX path. */
6
+ file: string;
7
+ /** Optional top-level symbol that must still exist in that file. */
8
+ symbol?: string;
9
+ };
10
+
11
+ export type SourceFinding = {
12
+ /** Repo-relative POSIX path. */
13
+ file: string;
14
+ /** 1-based. Diagnostic only; exceptions key on `match`, not on this. */
15
+ line: number;
16
+ /**
17
+ * The exact source text that triggered the finding (kept short, first ~60
18
+ * chars for larger nodes). This is what KNOWN_EXCEPTIONS keys on, so it
19
+ * must be stable under unrelated edits elsewhere in the file.
20
+ */
21
+ match: string;
22
+ message: string;
23
+ };
24
+
25
+ export type SourceCheck = {
26
+ /**
27
+ * Repo-relative globs. Explicit per project, because layouts differ:
28
+ * qpa-video/03_scenes/**\/*.jsx against revola-video/src/scenes/**\/*.tsx.
29
+ * "Scene files" is not a term this repo defines, so an implicit default
30
+ * would make each check's blast radius a guess.
31
+ */
32
+ include: string[];
33
+ /**
34
+ * Coarse escape hatch: globs a rule never applies to (a whole legacy
35
+ * subproject, a generated directory). Match-level KNOWN_EXCEPTIONS are the
36
+ * fine one. Merged into the runner's built-in ignore list.
37
+ */
38
+ exclude?: string[];
39
+ /** Pure over one parsed file. `relPath` is repo-relative POSIX; `root` is
40
+ * the absolute scan root `relPath` resolves against. Threaded explicitly
41
+ * because this package runs installed inside consumer repos, where any
42
+ * walk-up-from-module-location guess points at the wrong tree. */
43
+ run: (file: SourceFile, relPath: string, root: string) => SourceFinding[];
44
+ };
45
+
46
+ /**
47
+ * The pipeline stages an agent can be dispatched for. Stage assignment is an
48
+ * audience property (who must read a rule), not part of the rule's claim, so
49
+ * it lives in the central `STAGES` table in `stages.ts` rather than on each
50
+ * rule: one file is auditable at a glance, and a mis-scoped rule is a
51
+ * one-line fix instead of an edit buried among 100 rule files.
52
+ *
53
+ * Scoping narrows attention, never authority: every rule still binds every
54
+ * stage. CLAUDE.md carries the gates and any waived rule in full and names the
55
+ * rest by id (video-toolchain-cg6); HOW_I_BUILD_VIDEOS.md is the one doc with
56
+ * every rule's claim, why and provenance. Stage sheets
57
+ * exist so a dispatched vo:record agent does not spend its attention on seam
58
+ * geometry, which is how prose rules get paraphrased (Track B measured 9 of
59
+ * 22 declared names dropped from an all-prose contract).
60
+ */
61
+ export type Stage =
62
+ | "recon"
63
+ | "plan"
64
+ | "scene"
65
+ | "amplify"
66
+ | "review"
67
+ | "vo"
68
+ | "audio"
69
+ | "ship";
70
+
71
+ export type Scope =
72
+ | { kind: "pipeline" }
73
+ | {
74
+ kind: "component";
75
+ /** Kit component slug, e.g. "rolling-number". */
76
+ slug: string;
77
+ field: "whenToUse" | "whenNotToUse" | "gotcha";
78
+ };
79
+
80
+ export type Enforcement =
81
+ | { kind: "source"; check: SourceCheck }
82
+ | { kind: "prose"; anchor: CodeAnchor }
83
+ | { kind: "prose"; unanchorable: string };
84
+
85
+ /**
86
+ * How much a violation costs, which decides where the rule is projected.
87
+ *
88
+ * Trial 3 run 1 spent three of five rebuild rounds on one defect whose rule was
89
+ * read and ticked off, and lost a brand mark to a rule nobody could verify. The
90
+ * registry was a flat list at the time, so a rule that costs a rebuild round
91
+ * rendered identically to a note about comment hygiene, and an agent short on
92
+ * context had no basis for choosing which to keep.
93
+ *
94
+ * - `gate` a violation ships a broken film or blocks release. Must carry
95
+ * `verify`: the command or procedure that settles it.
96
+ * - `craft` applied by judgement while building. The bulk of the registry.
97
+ * - `process` how to work rather than what to draw - diff discipline, evidence,
98
+ * build notes. Verifiable from the session, not from the render.
99
+ */
100
+ export type Tier = "gate" | "craft" | "process";
101
+
102
+ /**
103
+ * A client-directed waiver scoped to one project. The rule stays in force
104
+ * everywhere else; inside `project` the decision is settled, and a session must
105
+ * not "fix" the violation back to compliance - that is exactly the failure this
106
+ * field exists to prevent, because the claims are projected into CLAUDE.md and
107
+ * an unwaivered claim reads as an instruction.
108
+ *
109
+ * A waiver is not a deletion: the rule's claim, why and provenance stay
110
+ * intact, and the exception names where the overriding decision is recorded so
111
+ * the next reader can weigh it rather than inherit it blindly.
112
+ */
113
+ export type RuleException = {
114
+ /** Project directory the waiver covers, e.g. "qse-qguard-video". */
115
+ project: string;
116
+ /** What was decided, one line. Names the decider when that is the point. */
117
+ decision: string;
118
+ /** Repo-relative POSIX path of the document recording the decision. */
119
+ recordedIn: string;
120
+ /**
121
+ * Named scope, finer than the whole project: a specific element (a
122
+ * component/symbol a finding's `where.symbol` names) the waiver covers.
123
+ * Omit for a film-wide waiver. At most one of `element`/`seam` is expected
124
+ * per exception - a waiver names either a standing element or a seam, not
125
+ * both - but that is a radar-side (`applyWaivers`) invariant, not enforced
126
+ * here.
127
+ */
128
+ element?: string;
129
+ /** Named scope: a specific seam (e.g. "once-stolen") the waiver covers,
130
+ * matched the same way `element` is - against a finding's `where.symbol`,
131
+ * since the radar's Finding schema carries no separate seam identity field. */
132
+ seam?: string;
133
+ };
134
+
135
+ export type Rule = {
136
+ /** Stable kebab-case id. Referenced from notes files, so it must not churn. */
137
+ id: string;
138
+ /** One imperative line. */
139
+ claim: string;
140
+ /** The concrete failure this prevents. */
141
+ why: string;
142
+ /**
143
+ * Required and deliberately un-defaulted. An optional tier would let every
144
+ * new rule land in whichever bucket the type happened to pick, which is the
145
+ * same silent-default failure that left every source check's `include` glob
146
+ * excluding qse-qguard-video for its entire build.
147
+ */
148
+ tier: Tier;
149
+ /**
150
+ * The command or one-line procedure that settles this rule, e.g.
151
+ * "video render-twice --project <dir> --comp <id>". Required on `gate`.
152
+ *
153
+ * A gate whose verify is a manual procedure is honest and useful: it states
154
+ * the check that is owed. A gate with no verify at all is a claim nobody can
155
+ * discharge, which is how `hero-fills-the-frame` was violated by a hero
156
+ * occupying a third of the screen - the words its own claim uses.
157
+ */
158
+ verify?: string;
159
+ /** Repo-relative path of the notes file it was mined from. History; immutable. */
160
+ learnedFrom: string;
161
+ /** Cite an upstream Remotion rule rather than restating it, e.g. "remotion:rules/timing.md". */
162
+ upstream?: string;
163
+ /** Per-project client-directed waivers. Rendered into every projection. */
164
+ exceptions?: RuleException[];
165
+ /**
166
+ * What discharges this rule's obligation in practice: either a radar
167
+ * check id (validated against the generated `radar-check-ids.json` - the
168
+ * check-id list crosses the video-cli/video-craft boundary as a generated
169
+ * artifact, the same direction `waiverProjection.ts` crosses it the other
170
+ * way, since craft must never runtime-import cli) or the literal string
171
+ * `"coherence"` for a rule the live coherence agent discharges by
172
+ * judgement rather than an automated check (e.g. `motion-density-floor`).
173
+ * Optional and un-projected onto every rule on purpose: most craft rules
174
+ * are outside the radar's domain entirely (a kit-pinning discipline, a
175
+ * process rule about diff hygiene) and naming an owner for one would be a
176
+ * fabricated claim, not a fact.
177
+ */
178
+ owner?: string;
179
+ scope: Scope;
180
+ enforcement: Enforcement;
181
+ };
@@ -0,0 +1,24 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { COMPONENT_VARIANTS } from "./variants";
3
+
4
+ describe("COMPONENT_VARIANTS", () => {
5
+ test("covers exactly the three Tier A components", () => {
6
+ expect(Object.keys(COMPONENT_VARIANTS).sort()).toEqual([
7
+ "animated-bar-chart",
8
+ "animated-line-chart",
9
+ "rolling-number",
10
+ ]);
11
+ });
12
+
13
+ test("every component has at least two variants and the default variant is listed first", () => {
14
+ expect(COMPONENT_VARIANTS["rolling-number"]).toEqual(["odometer", "slam"]);
15
+ expect(COMPONENT_VARIANTS["animated-bar-chart"]).toEqual(["grow", "cascade"]);
16
+ expect(COMPONENT_VARIANTS["animated-line-chart"]).toEqual(["draw", "sweep"]);
17
+ });
18
+
19
+ test("variant names are kebab-safe lowercase", () => {
20
+ for (const variants of Object.values(COMPONENT_VARIANTS)) {
21
+ for (const v of variants) expect(v).toMatch(/^[a-z0-9-]+$/);
22
+ }
23
+ });
24
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Declared variant unions per Tier A component slug: the single source of
3
+ * truth that generate.ts projects into the .meta.ts sidecars (and from there
4
+ * into the manifest). The kit closes the loop with a drift test asserting
5
+ * each component's exported *_VARIANTS const equals its sidecar's variants,
6
+ * so a variant added in only one place fails the suite.
7
+ * Order matters: the FIRST entry is the component's default variant.
8
+ */
9
+ export const COMPONENT_VARIANTS: Record<string, readonly string[]> = {
10
+ "rolling-number": ["odometer", "slam"],
11
+ "animated-bar-chart": ["grow", "cascade"],
12
+ "animated-line-chart": ["draw", "sweep"],
13
+ };
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { renderWaivers, renderWaiversJson } from "./waiverProjection";
3
+ import type { Rule } from "./types";
4
+
5
+ const rule = (over: Partial<Rule> = {}): Rule => ({
6
+ id: "some-rule",
7
+ claim: "c",
8
+ why: "w",
9
+ tier: "craft",
10
+ learnedFrom: "notes.md",
11
+ scope: { kind: "pipeline" },
12
+ enforcement: { kind: "prose", unanchorable: "no anchor" },
13
+ ...over,
14
+ });
15
+
16
+ describe("renderWaivers", () => {
17
+ it("projects every exception, tagged with its owning rule id", () => {
18
+ const rules = [rule({
19
+ id: "no-stacked-fades-at-a-cut",
20
+ exceptions: [{ project: "qse-qguard-video", decision: "d", recordedIn: "qse-qguard-video/docs/motion-brand-spec.md" }],
21
+ })];
22
+ expect(renderWaivers(rules)).toEqual([
23
+ { ruleId: "no-stacked-fades-at-a-cut", project: "qse-qguard-video", recordedIn: "qse-qguard-video/docs/motion-brand-spec.md" },
24
+ ]);
25
+ });
26
+
27
+ it("carries element/seam scope when the exception declares it", () => {
28
+ const rules = [rule({
29
+ id: "hero-fills-the-frame",
30
+ exceptions: [{ project: "acme-video", decision: "d", recordedIn: "acme-video/docs/spec.md", element: "logo" }],
31
+ })];
32
+ expect(renderWaivers(rules)[0]).toMatchObject({ element: "logo" });
33
+ expect(renderWaivers(rules)[0]).not.toHaveProperty("seam");
34
+ });
35
+
36
+ it("a rule with no exceptions contributes nothing", () => {
37
+ expect(renderWaivers([rule({ id: "no-exceptions-rule" })])).toEqual([]);
38
+ });
39
+
40
+ it("aggregates exceptions across every rule in the registry", () => {
41
+ const rules = [
42
+ rule({ id: "a", exceptions: [{ project: "p1", decision: "d", recordedIn: "p1/x.md" }] }),
43
+ rule({ id: "b", exceptions: [{ project: "p2", decision: "d", recordedIn: "p2/x.md" }] }),
44
+ ];
45
+ expect(renderWaivers(rules)).toHaveLength(2);
46
+ });
47
+ });
48
+
49
+ describe("renderWaiversJson", () => {
50
+ it("is deterministic (sorted) regardless of registry order", () => {
51
+ const a = rule({ id: "a", exceptions: [{ project: "p1", decision: "d", recordedIn: "p1/x.md" }] });
52
+ const b = rule({ id: "b", exceptions: [{ project: "p2", decision: "d", recordedIn: "p2/x.md" }] });
53
+ expect(renderWaiversJson([a, b])).toBe(renderWaiversJson([b, a]));
54
+ });
55
+
56
+ it("ends with a trailing newline", () => {
57
+ expect(renderWaiversJson([])).toBe("[]\n");
58
+ });
59
+ });
@@ -0,0 +1,45 @@
1
+ // Projects every rule's `exceptions` into the radar's waiver source. video-cli
2
+ // must not runtime-import video-craft (that drags ts-morph into the CLI, and
3
+ // craft already cannot import cli - see radar/waivers.ts's own header), so the
4
+ // bridge is a generated JSON file: `scripts/generate.ts` calls
5
+ // `renderWaiversJson` and writes `packages/video-cli/src/radar/
6
+ // waivers.generated.json`, exactly the `radar-check-ids.json` mechanism
7
+ // (Task 23) pointed the other way, with `drift.test.ts` guarding it never goes
8
+ // stale.
9
+ import type { Rule } from "./types";
10
+
11
+ export type RuleWaiver = {
12
+ ruleId?: string;
13
+ checkId?: string;
14
+ project: string;
15
+ element?: string;
16
+ seam?: string;
17
+ recordedIn: string;
18
+ };
19
+
20
+ /** Every rule's exceptions, flattened and tagged with the owning rule's id.
21
+ * No `checkId`-keyed waiver is ever produced from the registry - a rule
22
+ * without a stable radar checkId equivalent doesn't exist today, so that
23
+ * path (a check waivable by checkId alone) is fixture-tested only in
24
+ * `waivers.test.ts`, not sourced from here. */
25
+ export function renderWaivers(rules: Rule[]): RuleWaiver[] {
26
+ return rules.flatMap((rule) =>
27
+ (rule.exceptions ?? []).map((ex) => ({
28
+ ruleId: rule.id,
29
+ project: ex.project,
30
+ ...(ex.element !== undefined ? { element: ex.element } : {}),
31
+ ...(ex.seam !== undefined ? { seam: ex.seam } : {}),
32
+ recordedIn: ex.recordedIn,
33
+ })),
34
+ );
35
+ }
36
+
37
+ /** Sort key: same rule/project/scope always lands in the same place, so the
38
+ * generated file's bytes don't depend on registry array order - the drift
39
+ * test compares bytes, and a reordering-only change must not appear stale. */
40
+ const sortKey = (w: RuleWaiver): string => `${w.ruleId ?? w.checkId ?? ""}:${w.project}:${w.element ?? ""}:${w.seam ?? ""}`;
41
+
42
+ export function renderWaiversJson(rules: Rule[]): string {
43
+ const sorted = [...renderWaivers(rules)].sort((a, b) => (sortKey(a) < sortKey(b) ? -1 : sortKey(a) > sortKey(b) ? 1 : 0));
44
+ return JSON.stringify(sorted, null, 2) + "\n";
45
+ }