@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.
- package/README.md +56 -0
- package/dist/anchors.js +69 -0
- package/dist/corpus.js +91 -0
- package/dist/projectDoc.js +83 -0
- package/dist/projectDocSync.js +39 -0
- package/dist/projectMeta.js +37 -0
- package/dist/provenance.js +41 -0
- package/dist/radar-check-ids.json +34 -0
- package/dist/registry.js +307 -0
- package/dist/rules/animatedBarChartTightBox.js +15 -0
- package/dist/rules/animatedBarChartWhenNotToUse.js +15 -0
- package/dist/rules/animatedBarChartWhenToUse.js +15 -0
- package/dist/rules/animatedLineChartWhenNotToUse.js +15 -0
- package/dist/rules/animatedLineChartWhenToUse.js +15 -0
- package/dist/rules/approvedSfxPaletteOnly.js +15 -0
- package/dist/rules/atmosphereGradientsFadeAtBothEnds.js +15 -0
- package/dist/rules/audioIsTheClock.js +16 -0
- package/dist/rules/beatsDeriveFromTheirOwnSequence.js +15 -0
- package/dist/rules/bestSceneSetsTheBar.js +15 -0
- package/dist/rules/bumpBeforeRefreeze.js +15 -0
- package/dist/rules/cameraIsTheNarrator.js +15 -0
- package/dist/rules/checkPinBeforeShip.js +16 -0
- package/dist/rules/coldViewerClarity.js +15 -0
- package/dist/rules/commitOrCutEffects.js +29 -0
- package/dist/rules/convertFramesAcrossClockBoundary.js +15 -0
- package/dist/rules/crossCutElementsLiveInTheHudLayer.js +15 -0
- package/dist/rules/cursorClicksRealControls.js +15 -0
- package/dist/rules/cutOnRealAudioPauses.js +15 -0
- package/dist/rules/darkButNeverDim.js +15 -0
- package/dist/rules/dataRadarTagsDeclared.js +193 -0
- package/dist/rules/declareAVerticalZoneMap.js +15 -0
- package/dist/rules/deleteRejectedRigsCompletely.js +15 -0
- package/dist/rules/deriveSeamsDontMeasure.js +17 -0
- package/dist/rules/deterministicSceneSource.js +65 -0
- package/dist/rules/diegeticSoundForOnscreenActions.js +15 -0
- package/dist/rules/distinctTransitionPerBeat.js +15 -0
- package/dist/rules/downloadOrDrawRichAssets.js +15 -0
- package/dist/rules/elementOnscreenForItsVoSentence.js +17 -0
- package/dist/rules/emitBuildNotes.js +15 -0
- package/dist/rules/energyFromTimingNotPartCount.js +15 -0
- package/dist/rules/evidenceBeforeClaimingFixed.js +15 -0
- package/dist/rules/exactPeerLockstep.js +15 -0
- package/dist/rules/firstPassIsADraft.js +15 -0
- package/dist/rules/fixCrowdingByRebandingNotNudging.js +15 -0
- package/dist/rules/fixesPreserveApprovedElements.js +15 -0
- package/dist/rules/floatingNotBoxed.js +15 -0
- package/dist/rules/focusBeatsRecedeTheContext.js +15 -0
- package/dist/rules/fontVarsBrandRemocn.js +15 -0
- package/dist/rules/geometricSeamsNotCrossfades.js +23 -0
- package/dist/rules/geometrySidecarExportsTyped.js +36 -0
- package/dist/rules/glowIsAFocalAccent.js +22 -0
- package/dist/rules/heroFillsTheFrame.js +17 -0
- package/dist/rules/htmlMasksForAnimatedCounters.js +15 -0
- package/dist/rules/impactStackOnPayoffs.js +15 -0
- package/dist/rules/interactiveTargetsAreDeclaredData.js +15 -0
- package/dist/rules/interpolateLiteralKeysMonotonic.js +79 -0
- package/dist/rules/latenessIsStructuralOverlapTheBeats.js +15 -0
- package/dist/rules/lessTextMoreVisualizations.js +15 -0
- package/dist/rules/liveLinkDuplicateReactAlias.js +15 -0
- package/dist/rules/make2dElements3d.js +15 -0
- package/dist/rules/masterMixLoudnessTarget.js +17 -0
- package/dist/rules/measureAlignmentDontEyeball.js +15 -0
- package/dist/rules/motionCarriesWeightAndMeaning.js +15 -0
- package/dist/rules/motionDensityFloor.js +15 -0
- package/dist/rules/neverEditTierBVendored.js +15 -0
- package/dist/rules/neverRestateDerivedFrameNumbersInComments.js +15 -0
- package/dist/rules/noAiGradientLook.js +15 -0
- package/dist/rules/noColoredFlashToHideACut.js +22 -0
- package/dist/rules/noDoubleFrameShift.js +126 -0
- package/dist/rules/noDuplicateMotionPrimitives.js +15 -0
- package/dist/rules/noLinearMotion.js +22 -0
- package/dist/rules/noNestedSvgFilters.js +93 -0
- package/dist/rules/noRepeatedAssetAcrossShots.js +15 -0
- package/dist/rules/noShorthandWithUndefinedLonghand.js +93 -0
- package/dist/rules/noStackedFadesAtACut.js +24 -0
- package/dist/rules/noStaticHolds.js +17 -0
- package/dist/rules/occlusionVisibleElements.js +17 -0
- package/dist/rules/oneContinuousVoTrack.js +15 -0
- package/dist/rules/onePunchPerMomentClass.js +15 -0
- package/dist/rules/oneRenderPerRound.js +15 -0
- package/dist/rules/openStaticAfterAHardCut.js +22 -0
- package/dist/rules/openingsAndClosingsCarryMore.js +15 -0
- package/dist/rules/persistentDeviceFrames.js +15 -0
- package/dist/rules/pixelDiffAnEmptyBandFirst.js +15 -0
- package/dist/rules/planIsPublishedNotGating.js +15 -0
- package/dist/rules/poweredByRevolaWatermark.js +15 -0
- package/dist/rules/predrawContentPresentAtTheCut.js +17 -0
- package/dist/rules/premiumSurfacesNotFlatBorders.js +15 -0
- package/dist/rules/radarDispositionsAreHumanOnly.js +17 -0
- package/dist/rules/realAssetsNotPlaceholders.js +15 -0
- package/dist/rules/rebuildUiFromReconNotScreenshots.js +15 -0
- package/dist/rules/reconStrandsRunInParallel.js +15 -0
- package/dist/rules/registryBeforeHandrolling.js +15 -0
- package/dist/rules/remapRateEndpointFormula.js +15 -0
- package/dist/rules/remocnContentTailwindChrome.js +15 -0
- package/dist/rules/retimeOnlyViaPlaybackOrDesignTokens.js +15 -0
- package/dist/rules/reviewTheRenderByFrameSweep.js +15 -0
- package/dist/rules/rollingNumberBoundedSequence.js +17 -0
- package/dist/rules/rollingNumberSequenceLayoutNone.js +16 -0
- package/dist/rules/rollingNumberTightBoxAlignment.js +15 -0
- package/dist/rules/rollingNumberWhenNotToUse.js +17 -0
- package/dist/rules/rollingNumberWhenToUse.js +17 -0
- package/dist/rules/sameFamilySameProject.js +15 -0
- package/dist/rules/sampleBrandFromProduct.js +15 -0
- package/dist/rules/sampleVelocityFromPreviousFramePosition.js +15 -0
- package/dist/rules/sceneRootTagDeclared.js +41 -0
- package/dist/rules/scrubDemoDataToGenericRoles.js +15 -0
- package/dist/rules/selfReviewThePlanForGaps.js +15 -0
- package/dist/rules/sourceArchivedBeforeBrief.js +17 -0
- package/dist/rules/statisticsSelfExplanatory.js +15 -0
- package/dist/rules/stopsAsRelativeSpacing.js +15 -0
- package/dist/rules/theWholeCanvasWorks.js +15 -0
- package/dist/rules/themePerSection.js +22 -0
- package/dist/rules/thesisDeclaredInBrief.js +17 -0
- package/dist/rules/tierARequiresPropUnreachableEdit.js +15 -0
- package/dist/rules/tinyBodyCopyAsRuledLines.js +15 -0
- package/dist/rules/titlesPinnedOutsideCameraPush.js +15 -0
- package/dist/rules/tokensNotRawHexes.js +60 -0
- package/dist/rules/typeTokenDefaultedParamsAsString.js +15 -0
- package/dist/rules/varyKitChoreographyAcrossSections.js +15 -0
- package/dist/rules/varyTheVisualizationGrammar.js +15 -0
- package/dist/rules/verifyCheapRenderDear.js +15 -0
- package/dist/rules/voAddressesTheViewer.js +15 -0
- package/dist/rules/voIsAPerformance.js +15 -0
- package/dist/rules/voScriptLocksSpokenWords.js +15 -0
- package/dist/rules/wrappersPreserveChildGeometry.js +15 -0
- package/dist/sourceCheck.js +47 -0
- package/dist/sourceCitations.js +68 -0
- package/dist/stageProjection.js +69 -0
- package/dist/stages.js +163 -0
- package/dist/testSupport.js +6 -0
- package/dist/types.js +0 -0
- package/dist/variants.js +8 -0
- package/dist/waiverProjection.js +20 -0
- package/package.json +32 -0
- package/src/anchors.test.ts +119 -0
- package/src/anchors.ts +110 -0
- package/src/corpus.test.ts +96 -0
- package/src/corpus.ts +149 -0
- package/src/corpusProject.test.ts +103 -0
- package/src/creativeEdge.test.ts +58 -0
- package/src/distBuild.test.ts +86 -0
- package/src/docStatus.test.ts +81 -0
- package/src/drift.test.ts +124 -0
- package/src/fixtures/data-radar-dynamic/Branches.tsx +14 -0
- package/src/fixtures/data-radar-dynamic/plan.fixture.yaml +16 -0
- package/src/fixtures/data-radar-forwarded/Scene.tsx +19 -0
- package/src/fixtures/data-radar-forwarded/plan.fixture.yaml +13 -0
- package/src/fixtures/data-radar-opaque/Scene.tsx +15 -0
- package/src/fixtures/data-radar-opaque/plan.fixture.yaml +10 -0
- package/src/fixtures/data-radar-tags/SceneClean.tsx +10 -0
- package/src/fixtures/data-radar-tags/SceneNullBinding.tsx +12 -0
- package/src/fixtures/data-radar-tags/SceneWithGap.tsx +11 -0
- package/src/fixtures/data-radar-tags/plan.fixture.yaml +29 -0
- package/src/fixtures/deterministic-scene.tsx +15 -0
- package/src/fixtures/double-shift/aliased.tsx +13 -0
- package/src/fixtures/double-shift/assigned.tsx +13 -0
- package/src/fixtures/double-shift/clean.tsx +19 -0
- package/src/fixtures/double-shift/destructured.tsx +12 -0
- package/src/fixtures/double-shift/elementAccess.tsx +12 -0
- package/src/fixtures/double-shift/layout.ts +24 -0
- package/src/fixtures/double-shift/mechanism-prefix.tsx.txt +458 -0
- package/src/fixtures/double-shift/wrapped.tsx +15 -0
- package/src/fixtures/geometry-sidecar-missing-export.ts +10 -0
- package/src/fixtures/geometry-sidecar-missing-type.ts +7 -0
- package/src/fixtures/geometry-sidecar-valid.ts +6 -0
- package/src/fixtures/interpolate-ascending.tsx +6 -0
- package/src/fixtures/interpolate-descending.tsx +8 -0
- package/src/fixtures/interpolate-identifier-keys.tsx +9 -0
- package/src/fixtures/nested-filters-broken.tsx +11 -0
- package/src/fixtures/nested-filters-fixed.tsx +8 -0
- package/src/fixtures/nested-filters-html-wrapper.tsx +14 -0
- package/src/fixtures/nested-filters-html.tsx +7 -0
- package/src/fixtures/nested-filters-siblings.tsx +12 -0
- package/src/fixtures/nondeterministic-scene.tsx +14 -0
- package/src/fixtures/nondeterministic-variants.tsx +16 -0
- package/src/fixtures/raw-hex-scene.tsx +10 -0
- package/src/fixtures/scene-root-declared/SceneHook.tsx +9 -0
- package/src/fixtures/scene-root-declared/plan.fixture.yaml +10 -0
- package/src/fixtures/scene-root-missing/SceneHook.tsx +11 -0
- package/src/fixtures/scene-root-missing/plan.fixture.yaml +10 -0
- package/src/fixtures/scene-root-no-names/SceneHook.tsx +6 -0
- package/src/fixtures/scene-root-no-names/plan.fixture.yaml +6 -0
- package/src/fixtures/scene-root-shell/SceneHook.tsx +8 -0
- package/src/fixtures/scene-root-shell/Shell.tsx +9 -0
- package/src/fixtures/scene-root-shell/plan.fixture.yaml +10 -0
- package/src/fixtures/shorthand-undefined-clean.tsx +23 -0
- package/src/fixtures/shorthand-undefined-longhand.tsx +17 -0
- package/src/fixtures/token-scene.tsx +9 -0
- package/src/includeCoverage.test.ts +176 -0
- package/src/learnedFrom.test.ts +32 -0
- package/src/projectDoc.test.ts +230 -0
- package/src/projectDoc.ts +152 -0
- package/src/projectDocSync.test.ts +152 -0
- package/src/projectDocSync.ts +79 -0
- package/src/projectMeta.test.ts +75 -0
- package/src/projectMeta.ts +53 -0
- package/src/provenance.ts +85 -0
- package/src/radar-check-ids.json +34 -0
- package/src/registry.test.ts +207 -0
- package/src/registry.ts +352 -0
- package/src/rules/animatedBarChartTightBox.ts +14 -0
- package/src/rules/animatedBarChartWhenNotToUse.ts +14 -0
- package/src/rules/animatedBarChartWhenToUse.ts +14 -0
- package/src/rules/animatedLineChartWhenNotToUse.ts +14 -0
- package/src/rules/animatedLineChartWhenToUse.ts +14 -0
- package/src/rules/approvedSfxPaletteOnly.ts +23 -0
- package/src/rules/atmosphereGradientsFadeAtBothEnds.ts +21 -0
- package/src/rules/audioIsTheClock.ts +22 -0
- package/src/rules/beatsDeriveFromTheirOwnSequence.ts +21 -0
- package/src/rules/bestSceneSetsTheBar.ts +21 -0
- package/src/rules/bumpBeforeRefreeze.ts +20 -0
- package/src/rules/cameraIsTheNarrator.ts +21 -0
- package/src/rules/checkPinBeforeShip.ts +22 -0
- package/src/rules/coldViewerClarity.ts +21 -0
- package/src/rules/commitOrCutEffects.ts +36 -0
- package/src/rules/convertFramesAcrossClockBoundary.ts +19 -0
- package/src/rules/crossCutElementsLiveInTheHudLayer.ts +21 -0
- package/src/rules/cursorClicksRealControls.ts +22 -0
- package/src/rules/cutOnRealAudioPauses.ts +20 -0
- package/src/rules/darkButNeverDim.ts +21 -0
- package/src/rules/dataRadarTagsDeclared.test.ts +60 -0
- package/src/rules/dataRadarTagsDeclared.ts +341 -0
- package/src/rules/declareAVerticalZoneMap.ts +19 -0
- package/src/rules/deleteRejectedRigsCompletely.ts +19 -0
- package/src/rules/deriveSeamsDontMeasure.ts +23 -0
- package/src/rules/deterministicSceneSource.test.ts +58 -0
- package/src/rules/deterministicSceneSource.ts +82 -0
- package/src/rules/diegeticSoundForOnscreenActions.ts +21 -0
- package/src/rules/distinctTransitionPerBeat.ts +21 -0
- package/src/rules/downloadOrDrawRichAssets.ts +22 -0
- package/src/rules/elementOnscreenForItsVoSentence.ts +25 -0
- package/src/rules/emitBuildNotes.ts +19 -0
- package/src/rules/energyFromTimingNotPartCount.ts +20 -0
- package/src/rules/evidenceBeforeClaimingFixed.ts +23 -0
- package/src/rules/exactPeerLockstep.ts +19 -0
- package/src/rules/firstPassIsADraft.ts +20 -0
- package/src/rules/fixCrowdingByRebandingNotNudging.ts +20 -0
- package/src/rules/fixesPreserveApprovedElements.ts +24 -0
- package/src/rules/floatingNotBoxed.ts +21 -0
- package/src/rules/focusBeatsRecedeTheContext.ts +20 -0
- package/src/rules/fontVarsBrandRemocn.ts +20 -0
- package/src/rules/geometricSeamsNotCrossfades.ts +28 -0
- package/src/rules/geometrySidecarExportsTyped.test.ts +37 -0
- package/src/rules/geometrySidecarExportsTyped.ts +59 -0
- package/src/rules/glowIsAFocalAccent.ts +28 -0
- package/src/rules/heroFillsTheFrame.ts +24 -0
- package/src/rules/htmlMasksForAnimatedCounters.ts +21 -0
- package/src/rules/impactStackOnPayoffs.ts +26 -0
- package/src/rules/interactiveTargetsAreDeclaredData.ts +21 -0
- package/src/rules/interpolateLiteralKeysMonotonic.test.ts +49 -0
- package/src/rules/interpolateLiteralKeysMonotonic.ts +98 -0
- package/src/rules/latenessIsStructuralOverlapTheBeats.ts +20 -0
- package/src/rules/lessTextMoreVisualizations.ts +22 -0
- package/src/rules/liveLinkDuplicateReactAlias.ts +22 -0
- package/src/rules/make2dElements3d.ts +21 -0
- package/src/rules/masterMixLoudnessTarget.ts +22 -0
- package/src/rules/measureAlignmentDontEyeball.ts +20 -0
- package/src/rules/motionCarriesWeightAndMeaning.ts +21 -0
- package/src/rules/motionDensityFloor.ts +20 -0
- package/src/rules/neverEditTierBVendored.ts +20 -0
- package/src/rules/neverRestateDerivedFrameNumbersInComments.ts +20 -0
- package/src/rules/noAiGradientLook.ts +22 -0
- package/src/rules/noColoredFlashToHideACut.ts +29 -0
- package/src/rules/noDoubleFrameShift.test.ts +95 -0
- package/src/rules/noDoubleFrameShift.ts +193 -0
- package/src/rules/noDuplicateMotionPrimitives.ts +19 -0
- package/src/rules/noLinearMotion.ts +29 -0
- package/src/rules/noNestedSvgFilters.test.ts +47 -0
- package/src/rules/noNestedSvgFilters.ts +138 -0
- package/src/rules/noRepeatedAssetAcrossShots.ts +19 -0
- package/src/rules/noShorthandWithUndefinedLonghand.test.ts +35 -0
- package/src/rules/noShorthandWithUndefinedLonghand.ts +140 -0
- package/src/rules/noStackedFadesAtACut.ts +30 -0
- package/src/rules/noStaticHolds.ts +24 -0
- package/src/rules/occlusionVisibleElements.ts +26 -0
- package/src/rules/oneContinuousVoTrack.ts +20 -0
- package/src/rules/onePunchPerMomentClass.ts +20 -0
- package/src/rules/oneRenderPerRound.ts +46 -0
- package/src/rules/openStaticAfterAHardCut.ts +29 -0
- package/src/rules/openingsAndClosingsCarryMore.ts +21 -0
- package/src/rules/persistentDeviceFrames.ts +20 -0
- package/src/rules/pixelDiffAnEmptyBandFirst.ts +20 -0
- package/src/rules/planIsPublishedNotGating.ts +32 -0
- package/src/rules/poweredByRevolaWatermark.ts +19 -0
- package/src/rules/predrawContentPresentAtTheCut.ts +21 -0
- package/src/rules/premiumSurfacesNotFlatBorders.ts +20 -0
- package/src/rules/radarDispositionsAreHumanOnly.ts +28 -0
- package/src/rules/realAssetsNotPlaceholders.ts +21 -0
- package/src/rules/rebuildUiFromReconNotScreenshots.ts +21 -0
- package/src/rules/reconStrandsRunInParallel.ts +63 -0
- package/src/rules/registryBeforeHandrolling.ts +20 -0
- package/src/rules/remapRateEndpointFormula.ts +19 -0
- package/src/rules/remocnContentTailwindChrome.ts +19 -0
- package/src/rules/retimeOnlyViaPlaybackOrDesignTokens.ts +18 -0
- package/src/rules/reviewTheRenderByFrameSweep.ts +23 -0
- package/src/rules/rollingNumberBoundedSequence.ts +21 -0
- package/src/rules/rollingNumberSequenceLayoutNone.ts +22 -0
- package/src/rules/rollingNumberTightBoxAlignment.ts +19 -0
- package/src/rules/rollingNumberWhenNotToUse.ts +24 -0
- package/src/rules/rollingNumberWhenToUse.ts +23 -0
- package/src/rules/sameFamilySameProject.ts +20 -0
- package/src/rules/sampleBrandFromProduct.ts +19 -0
- package/src/rules/sampleVelocityFromPreviousFramePosition.ts +21 -0
- package/src/rules/sceneRootTagDeclared.test.ts +43 -0
- package/src/rules/sceneRootTagDeclared.ts +78 -0
- package/src/rules/scrubDemoDataToGenericRoles.ts +19 -0
- package/src/rules/selfReviewThePlanForGaps.ts +47 -0
- package/src/rules/sourceArchivedBeforeBrief.ts +24 -0
- package/src/rules/statisticsSelfExplanatory.ts +18 -0
- package/src/rules/stopsAsRelativeSpacing.ts +21 -0
- package/src/rules/theWholeCanvasWorks.ts +21 -0
- package/src/rules/themePerSection.ts +28 -0
- package/src/rules/thesisDeclaredInBrief.ts +25 -0
- package/src/rules/tierARequiresPropUnreachableEdit.ts +20 -0
- package/src/rules/tinyBodyCopyAsRuledLines.ts +19 -0
- package/src/rules/titlesPinnedOutsideCameraPush.ts +22 -0
- package/src/rules/tokensNotRawHexes.test.ts +51 -0
- package/src/rules/tokensNotRawHexes.ts +89 -0
- package/src/rules/typeTokenDefaultedParamsAsString.ts +21 -0
- package/src/rules/varyKitChoreographyAcrossSections.ts +21 -0
- package/src/rules/varyTheVisualizationGrammar.ts +22 -0
- package/src/rules/verifyCheapRenderDear.ts +18 -0
- package/src/rules/voAddressesTheViewer.ts +18 -0
- package/src/rules/voIsAPerformance.ts +21 -0
- package/src/rules/voScriptLocksSpokenWords.ts +21 -0
- package/src/rules/wrappersPreserveChildGeometry.ts +22 -0
- package/src/sourceCheck.test.ts +50 -0
- package/src/sourceCheck.ts +55 -0
- package/src/sourceCitations.test.ts +747 -0
- package/src/sourceCitations.ts +217 -0
- package/src/stageProjection.ts +112 -0
- package/src/stages.test.ts +68 -0
- package/src/stages.ts +207 -0
- package/src/testSupport.ts +16 -0
- package/src/types.ts +181 -0
- package/src/variants.test.ts +24 -0
- package/src/variants.ts +13 -0
- package/src/waiverProjection.test.ts +59 -0
- package/src/waiverProjection.ts +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @revola-ai/video-craft
|
|
2
|
+
|
|
3
|
+
Durable craft knowledge for building videos in this repo, as machine-checked rules.
|
|
4
|
+
|
|
5
|
+
## Adding a rule
|
|
6
|
+
|
|
7
|
+
Pick the track that fits, then finish with the shared steps below.
|
|
8
|
+
|
|
9
|
+
**Prose rule, anchored** (a lesson that points at live code):
|
|
10
|
+
copy `src/rules/deriveSeamsDontMeasure.ts`. Anchor to a durable home - an
|
|
11
|
+
exported kit symbol or a long-lived helper - over a scene-local constant.
|
|
12
|
+
If an anchor later dangles, re-anchor it to where the evidence now lives;
|
|
13
|
+
never flip it to `unanchorable` to silence the test.
|
|
14
|
+
|
|
15
|
+
**Prose rule, unanchorable** (process guidance with no code to point at):
|
|
16
|
+
copy `src/rules/deleteRejectedRigsCompletely.ts`. The `unanchorable` string
|
|
17
|
+
must say why, and when to re-anchor if that changes.
|
|
18
|
+
|
|
19
|
+
**Source rule** (mechanically checkable in scene source):
|
|
20
|
+
copy `src/rules/noNestedSvgFilters.ts`. Also required: a fixture pair under
|
|
21
|
+
`src/fixtures/` (broken shape fires, fixed shape does not, plus a
|
|
22
|
+
false-positive guard), a `src/rules/<name>.test.ts`, and a clean run over the
|
|
23
|
+
corpus - `src/corpus.test.ts` fails on any finding that is not a justified
|
|
24
|
+
`KNOWN_EXCEPTIONS` entry naming a recorded follow-up. `include` globs are
|
|
25
|
+
explicit per project; `exclude` is the coarse escape hatch for files a rule
|
|
26
|
+
never applies to.
|
|
27
|
+
|
|
28
|
+
**Component rule** (feeds a kit sidecar): set
|
|
29
|
+
`scope: { kind: "component", slug, field }`. `whenToUse` and `whenNotToUse`
|
|
30
|
+
allow one rule each per component - pick the crispest sentence.
|
|
31
|
+
|
|
32
|
+
**Shared steps, in order:**
|
|
33
|
+
|
|
34
|
+
1. Register the rule in `src/registry.ts`.
|
|
35
|
+
2. Run `npx tsx packages/video-craft/scripts/generate.ts` (validates the
|
|
36
|
+
registry, then rewrites the outputs below).
|
|
37
|
+
3. Run `./node_modules/.bin/tsc -p tsconfig.json --noEmit` - vitest does NOT
|
|
38
|
+
typecheck, and a malformed `Rule` literal is a type error, not a test
|
|
39
|
+
failure.
|
|
40
|
+
4. Run `./node_modules/.bin/vitest run packages/video-craft`.
|
|
41
|
+
5. Add a back-reference (`(Rule: \`<id>\`.)`) to the notes passage it was
|
|
42
|
+
mined from.
|
|
43
|
+
|
|
44
|
+
Skipping step 2 makes the drift tests fail with a stale-file diff: run the
|
|
45
|
+
generator, never hand-edit the generated files.
|
|
46
|
+
|
|
47
|
+
## Outputs (machine-owned - do not hand-edit)
|
|
48
|
+
|
|
49
|
+
- `packages/video-kit/src/motion/<slug>.meta.ts` - one per component with rules.
|
|
50
|
+
- The `craft:begin pipeline` block in `HOW_I_BUILD_VIDEOS.md`.
|
|
51
|
+
|
|
52
|
+
Component rules are discoverable through the sidecars, pipeline rules through
|
|
53
|
+
the doc block; `src/registry.ts` is the complete list.
|
|
54
|
+
|
|
55
|
+
Every rule needs a `learnedFrom`: a rule with no origin is an opinion, not
|
|
56
|
+
knowledge. The verifier fails if that file disappears.
|
package/dist/anchors.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { Project, ts } from "ts-morph";
|
|
4
|
+
import { isUpstreamProvenance, upstreamCitationError } from "./provenance.js";
|
|
5
|
+
function provenanceError(path, root) {
|
|
6
|
+
if (isUpstreamProvenance(path)) {
|
|
7
|
+
const malformed = upstreamCitationError(path);
|
|
8
|
+
return malformed ? `is a malformed upstream citation (${malformed})` : void 0;
|
|
9
|
+
}
|
|
10
|
+
return existsSync(join(root, path)) ? void 0 : "does not exist";
|
|
11
|
+
}
|
|
12
|
+
function verifyAnchors(rules, root) {
|
|
13
|
+
const errors = [];
|
|
14
|
+
const project = new Project({
|
|
15
|
+
useInMemoryFileSystem: false,
|
|
16
|
+
skipAddingFilesFromTsConfig: true,
|
|
17
|
+
compilerOptions: { allowJs: true, jsx: ts.JsxEmit.ReactJSX }
|
|
18
|
+
});
|
|
19
|
+
for (const rule of rules) {
|
|
20
|
+
if (rule.learnedFrom) {
|
|
21
|
+
const bad = provenanceError(rule.learnedFrom, root);
|
|
22
|
+
if (bad) {
|
|
23
|
+
errors.push(`rule "${rule.id}": learnedFrom "${rule.learnedFrom}" ${bad}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for (const ex of rule.exceptions ?? []) {
|
|
27
|
+
const badRecord = provenanceError(ex.recordedIn, root);
|
|
28
|
+
if (badRecord) {
|
|
29
|
+
errors.push(
|
|
30
|
+
`rule "${rule.id}": exception recordedIn "${ex.recordedIn}" ${badRecord}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
const badProject = provenanceError(ex.project, root);
|
|
34
|
+
if (badProject) {
|
|
35
|
+
errors.push(`rule "${rule.id}": exception project "${ex.project}" ${badProject}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (rule.enforcement.kind !== "prose") continue;
|
|
39
|
+
if (!("anchor" in rule.enforcement)) continue;
|
|
40
|
+
const { file, symbol } = rule.enforcement.anchor;
|
|
41
|
+
if (isUpstreamProvenance(file)) {
|
|
42
|
+
const malformed = upstreamCitationError(file);
|
|
43
|
+
if (malformed) {
|
|
44
|
+
errors.push(
|
|
45
|
+
`rule "${rule.id}": anchor file "${file}" is a malformed upstream citation (${malformed})`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const abs = join(root, file);
|
|
51
|
+
if (!existsSync(abs)) {
|
|
52
|
+
errors.push(`rule "${rule.id}": anchor file "${file}" does not exist`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (!symbol) continue;
|
|
56
|
+
const source = project.getSourceFile(abs) ?? project.addSourceFileAtPath(abs);
|
|
57
|
+
const exported = source.getExportedDeclarations().has(symbol);
|
|
58
|
+
const local = source.getVariableDeclaration(symbol) !== void 0 || source.getFunction(symbol) !== void 0 || source.getInterface(symbol) !== void 0 || source.getTypeAlias(symbol) !== void 0;
|
|
59
|
+
if (!exported && !local) {
|
|
60
|
+
errors.push(
|
|
61
|
+
`rule "${rule.id}": anchor symbol "${symbol}" no longer exists in "${file}" - re-anchor the rule to where the evidence now lives; do not flip it to unanchorable`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return errors;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
verifyAnchors
|
|
69
|
+
};
|
package/dist/corpus.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { RULES } from "./registry.js";
|
|
2
|
+
import { matchedFiles, runSourceCheck } from "./sourceCheck.js";
|
|
3
|
+
const HEX_RULE = "tokens-not-raw-hexes";
|
|
4
|
+
const PANEL_FILL = "dark panel fill predates the rule; follow-up: tokenize into CK";
|
|
5
|
+
const BG_RESTATED = "raw restatement of CK.bg (#0b0b0d) predates the rule; follow-up: reference the token";
|
|
6
|
+
const HUE_RESTATED = "avatar hue pair restates CK accent tokens raw; predates the rule; follow-up: reference the tokens";
|
|
7
|
+
const LAVENDER = "lavender text tint (#c9b8fb) has no CK token yet; predates the rule; follow-up: tokenize into CK";
|
|
8
|
+
const ROCKET = "rocket illustration fill has no CK token yet; predates the rule; follow-up: tokenize into CK";
|
|
9
|
+
const KNOWN_EXCEPTIONS = [
|
|
10
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S3Line.tsx", match: "#15141d", justification: PANEL_FILL },
|
|
11
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S3Line.tsx", match: "#1c1a26", justification: PANEL_FILL },
|
|
12
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S3Line.tsx", match: "#14131c", justification: PANEL_FILL },
|
|
13
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S4Proof.tsx", match: "#16151e", justification: PANEL_FILL },
|
|
14
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S2Turn.tsx", match: "#0b0b0d", justification: BG_RESTATED },
|
|
15
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S4Proof.tsx", match: "#0b0b0d", justification: BG_RESTATED },
|
|
16
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/craftKit.tsx", match: "#0b0b0d", justification: BG_RESTATED },
|
|
17
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#8B5CF6", justification: HUE_RESTATED },
|
|
18
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#5CA4F6", justification: HUE_RESTATED },
|
|
19
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#5fd39a", justification: HUE_RESTATED },
|
|
20
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#f8b8aa", justification: HUE_RESTATED },
|
|
21
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#f5d67a", justification: HUE_RESTATED },
|
|
22
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/S5Mirror.tsx", match: "#c9b8fb", justification: LAVENDER },
|
|
23
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/ink.tsx", match: "#f5c66d", justification: ROCKET },
|
|
24
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/ink.tsx", match: "#2a2833", justification: ROCKET },
|
|
25
|
+
{ rule: HEX_RULE, file: "revola-video/src/scenes/craft/ink.tsx", match: "#bda6ff", justification: ROCKET },
|
|
26
|
+
// v2 (build2) frame-windowed carrier/hero binding: the tag is gated off over
|
|
27
|
+
// the seam-flight/vacate window (so hero-size never measures the shrinking
|
|
28
|
+
// carrier and no post-cue pose trips a geometry check), which a string literal
|
|
29
|
+
// cannot express; the runtime tag coverage (radar:scene tag-coverage, 22/22)
|
|
30
|
+
// still verifies every binding against sampled frames during its cues.
|
|
31
|
+
// Follow-up: remotion-videos-emp (source-evaluable hero/carrier windows).
|
|
32
|
+
{
|
|
33
|
+
rule: "data-radar-tags-declared",
|
|
34
|
+
file: "rcp-fund7-video/src/scenes/insurers.tsx",
|
|
35
|
+
match: 'data-radar={f < T_VACATE ? "insurer-edifice" : undefined}',
|
|
36
|
+
justification: "frame-windowed carrier tag gated off during the closing travel; runtime tag-coverage (22/22) verifies insurer-edifice during its cues. follow-up: remotion-videos-s300"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
rule: "data-radar-tags-declared",
|
|
40
|
+
file: "rcp-fund7-video/src/surfaces.tsx",
|
|
41
|
+
match: "data-radar={radarId}",
|
|
42
|
+
justification: "Panel forwards its tag via the radarId prop (call sites pass literals); the gate only traces props named dataRadar. Runtime tag-coverage verifies the bindings. follow-up: remotion-videos-s300 (rename prop to dataRadar)"
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
function corpusFindings(root) {
|
|
46
|
+
const out = [];
|
|
47
|
+
for (const rule of RULES) {
|
|
48
|
+
if (rule.enforcement.kind !== "source") continue;
|
|
49
|
+
for (const finding of runSourceCheck(rule.enforcement.check, root)) {
|
|
50
|
+
out.push({ ...finding, rule: rule.id });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
const findingKey = (f) => `${f.rule}|${f.file}|${f.match}`;
|
|
56
|
+
const scopedInclude = (include, projectName) => include.flatMap((glob) => {
|
|
57
|
+
const [head, ...rest] = glob.split("/");
|
|
58
|
+
if (head === projectName) return [glob];
|
|
59
|
+
if (head === "*" || head === "**") return [[projectName, ...rest].join("/")];
|
|
60
|
+
return [];
|
|
61
|
+
});
|
|
62
|
+
function scanProject(root, projectName) {
|
|
63
|
+
const findings = [];
|
|
64
|
+
const excused = [];
|
|
65
|
+
const coveredRules = [];
|
|
66
|
+
const uncoveredRules = [];
|
|
67
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
68
|
+
const excusedKeys = new Set(KNOWN_EXCEPTIONS.map(findingKey));
|
|
69
|
+
for (const rule of RULES) {
|
|
70
|
+
if (rule.enforcement.kind !== "source") continue;
|
|
71
|
+
const include = scopedInclude(rule.enforcement.check.include, projectName);
|
|
72
|
+
if (include.length === 0) {
|
|
73
|
+
uncoveredRules.push(rule.id);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
coveredRules.push(rule.id);
|
|
77
|
+
const check = { ...rule.enforcement.check, include };
|
|
78
|
+
for (const abs of matchedFiles(check, root)) scanned.add(abs);
|
|
79
|
+
for (const finding of runSourceCheck(check, root)) {
|
|
80
|
+
const f = { ...finding, rule: rule.id };
|
|
81
|
+
(excusedKeys.has(findingKey(f)) ? excused : findings).push(f);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { findings, excused, coveredRules, uncoveredRules, scannedFiles: scanned.size };
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
KNOWN_EXCEPTIONS,
|
|
88
|
+
corpusFindings,
|
|
89
|
+
findingKey,
|
|
90
|
+
scanProject
|
|
91
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const exceptionLines = (r, indent) => (r.exceptions ?? []).map(
|
|
2
|
+
(ex) => `${indent}- waived in \`${ex.project}\`: ${ex.decision} (recorded: \`${ex.recordedIn}\`)`
|
|
3
|
+
);
|
|
4
|
+
function spliceBlock(doc, marker, body) {
|
|
5
|
+
const begin = `<!-- craft:begin ${marker} -->`;
|
|
6
|
+
const end = `<!-- craft:end ${marker} -->`;
|
|
7
|
+
const from = doc.indexOf(begin);
|
|
8
|
+
if (from === -1) throw new Error(`marker "craft:begin ${marker}" not found`);
|
|
9
|
+
const to = doc.indexOf(end, from);
|
|
10
|
+
if (to === -1) throw new Error(`marker "craft:end ${marker}" not found`);
|
|
11
|
+
return doc.slice(0, from + begin.length) + "\n" + body + "\n" + doc.slice(to);
|
|
12
|
+
}
|
|
13
|
+
function renderClaudeMdBlock(rules, { compact = true } = {}) {
|
|
14
|
+
const pipeline = rules.filter((r) => r.scope.kind === "pipeline").sort((a, b) => a.id.localeCompare(b.id));
|
|
15
|
+
const of = (tier) => pipeline.filter((r) => r.tier === tier);
|
|
16
|
+
const isWaived = (r) => (r.exceptions ?? []).length > 0;
|
|
17
|
+
const section = (heading, body) => body.length === 0 ? [] : [...heading, ``, ...body, ``];
|
|
18
|
+
const full = (r) => [`- ${r.claim} (\`${r.id}\`)`, ...exceptionLines(r, " ")].join("\n");
|
|
19
|
+
const compacted = (rs, label) => {
|
|
20
|
+
if (rs.length === 0) return [];
|
|
21
|
+
if (!compact) return rs.map(full);
|
|
22
|
+
const waived = rs.filter(isWaived);
|
|
23
|
+
const plain = rs.filter((r) => !isWaived(r));
|
|
24
|
+
return [
|
|
25
|
+
...waived.map(full),
|
|
26
|
+
...waived.length && plain.length ? [``] : [],
|
|
27
|
+
...plain.length ? [
|
|
28
|
+
// Wording is load-bearing and was wrong in review twice over. "further"
|
|
29
|
+
// dangles in a tier with no waived rules above it (process has none).
|
|
30
|
+
// And the lookup recipe must key on what the reader HOLDS - an id -
|
|
31
|
+
// not on the heading text: renderPipelineBlock emits `### <claim>`, so
|
|
32
|
+
// the id appears only in the `Rule id:` line two lines below. Naming
|
|
33
|
+
// the wrong token would send every lookup into a 139 KB scan, which is
|
|
34
|
+
// the one thing this compaction cannot afford to get wrong.
|
|
35
|
+
`${plain.length} more ${label} rule${plain.length === 1 ? "" : "s"} bind${plain.length === 1 ? "s" : ""} this work, listed by id below. To read one, search HOW_I_BUILD_VIDEOS.md for its id in a \`Rule id:\` line - the headings there are the claims themselves, so the id is not a heading. That is the only doc carrying each rule's why and provenance; the per-stage sheets under \`docs/rules/stages/\` carry the claims, scoped by stage. Every id here is a rule you are accountable to, not a suggestion.`,
|
|
36
|
+
``,
|
|
37
|
+
plain.map((r) => `\`${r.id}\``).join(", ")
|
|
38
|
+
] : []
|
|
39
|
+
];
|
|
40
|
+
};
|
|
41
|
+
return [
|
|
42
|
+
`<!-- This block is generated from packages/video-craft/src/rules/. Do not edit it here. -->`,
|
|
43
|
+
``,
|
|
44
|
+
...section(
|
|
45
|
+
[
|
|
46
|
+
`### Gates - if you remember nothing else`,
|
|
47
|
+
``,
|
|
48
|
+
`Each line below has cost a rebuild round. Every one is settled by running something, not by reading the diff: run the check.`
|
|
49
|
+
],
|
|
50
|
+
of("gate").map(
|
|
51
|
+
(r) => [`- ${r.claim} (\`${r.id}\`)`, ` - verify: ${r.verify}`, ...exceptionLines(r, " ")].join("\n")
|
|
52
|
+
)
|
|
53
|
+
),
|
|
54
|
+
...section([`### Craft rules`], compacted(of("craft"), "craft")),
|
|
55
|
+
...section([`### Process rules`], compacted(of("process"), "process"))
|
|
56
|
+
].join("\n").trimEnd();
|
|
57
|
+
}
|
|
58
|
+
function renderPipelineBlock(rules) {
|
|
59
|
+
const pipeline = rules.filter((r) => r.scope.kind === "pipeline").sort((a, b) => a.id.localeCompare(b.id));
|
|
60
|
+
return [
|
|
61
|
+
`<!-- This block is generated from packages/video-craft/src/rules/. Do not edit it here. -->`,
|
|
62
|
+
``,
|
|
63
|
+
...pipeline.flatMap((r) => [
|
|
64
|
+
`### ${r.claim}`,
|
|
65
|
+
``,
|
|
66
|
+
r.why,
|
|
67
|
+
``,
|
|
68
|
+
// The tier is restated here rather than only in the CLAUDE.md projection
|
|
69
|
+
// so the reference doc and the injected block cannot disagree about how
|
|
70
|
+
// much a rule weighs - a reader who arrives via a rule id from a build
|
|
71
|
+
// note lands here, not there.
|
|
72
|
+
`Learned from \`${r.learnedFrom}\`. Rule id: \`${r.id}\`. Tier: ${r.tier}.`,
|
|
73
|
+
...r.verify ? [``, `Verify: ${r.verify}`] : [],
|
|
74
|
+
...(r.exceptions ?? []).length > 0 ? [``, ...exceptionLines(r, "")] : [],
|
|
75
|
+
``
|
|
76
|
+
])
|
|
77
|
+
].join("\n").trimEnd();
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
renderClaudeMdBlock,
|
|
81
|
+
renderPipelineBlock,
|
|
82
|
+
spliceBlock
|
|
83
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { renderClaudeMdBlock, renderPipelineBlock, spliceBlock } from "./projectDoc.js";
|
|
4
|
+
import { RULES } from "./registry.js";
|
|
5
|
+
function syncProjectedDocs(targetRoot, opts) {
|
|
6
|
+
const updated = [];
|
|
7
|
+
const skipped = [];
|
|
8
|
+
const claudePath = join(targetRoot, "CLAUDE.md");
|
|
9
|
+
if (!existsSync(claudePath)) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
`CLAUDE.md does not exist in ${targetRoot} - rules:sync splices into existing files and never creates them. Create CLAUDE.md with the craft markers (<!-- craft:begin claude-md --> / <!-- craft:end claude-md -->) first.`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
const howPath = join(targetRoot, "HOW_I_BUILD_VIDEOS.md");
|
|
15
|
+
const hasHow = existsSync(howPath);
|
|
16
|
+
writeFileSync(
|
|
17
|
+
claudePath,
|
|
18
|
+
spliceBlock(readFileSync(claudePath, "utf8"), "claude-md", renderClaudeMdBlock(RULES, { compact: hasHow })),
|
|
19
|
+
"utf8"
|
|
20
|
+
);
|
|
21
|
+
updated.push("CLAUDE.md");
|
|
22
|
+
if (opts?.claudeMdOnly) {
|
|
23
|
+
return { updated, skipped };
|
|
24
|
+
}
|
|
25
|
+
if (!hasHow) {
|
|
26
|
+
skipped.push({ file: "HOW_I_BUILD_VIDEOS.md", reason: "not present in target" });
|
|
27
|
+
} else {
|
|
28
|
+
writeFileSync(
|
|
29
|
+
howPath,
|
|
30
|
+
spliceBlock(readFileSync(howPath, "utf8"), "pipeline", renderPipelineBlock(RULES)),
|
|
31
|
+
"utf8"
|
|
32
|
+
);
|
|
33
|
+
updated.push("HOW_I_BUILD_VIDEOS.md");
|
|
34
|
+
}
|
|
35
|
+
return { updated, skipped };
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
syncProjectedDocs
|
|
39
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { COMPONENT_VARIANTS } from "./variants.js";
|
|
2
|
+
const forComponent = (rules, slug, field) => rules.filter((r) => r.scope.kind === "component" && r.scope.slug === slug && r.scope.field === field).sort((a, b) => a.id.localeCompare(b.id)).map((r) => r.claim);
|
|
3
|
+
function componentSlugs(rules) {
|
|
4
|
+
const slugs = /* @__PURE__ */ new Set();
|
|
5
|
+
for (const rule of rules) {
|
|
6
|
+
if (rule.scope.kind === "component") slugs.add(rule.scope.slug);
|
|
7
|
+
}
|
|
8
|
+
return [...slugs].sort();
|
|
9
|
+
}
|
|
10
|
+
const lit = (s) => JSON.stringify(s);
|
|
11
|
+
function renderComponentMeta(rules, slug) {
|
|
12
|
+
const whenToUse = forComponent(rules, slug, "whenToUse")[0] ?? "";
|
|
13
|
+
const whenNotToUse = forComponent(rules, slug, "whenNotToUse")[0] ?? "";
|
|
14
|
+
const gotchas = forComponent(rules, slug, "gotcha");
|
|
15
|
+
const name = slug.replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + "Meta";
|
|
16
|
+
const variants = COMPONENT_VARIANTS[slug] ?? [];
|
|
17
|
+
return [
|
|
18
|
+
`// GENERATED FILE - DO NOT EDIT.`,
|
|
19
|
+
`// Source of truth: packages/video-craft/src/rules/. Regenerate with:`,
|
|
20
|
+
`// npx tsx packages/video-craft/scripts/generate.ts`,
|
|
21
|
+
`// Edits here are reverted by the drift test in packages/video-craft/src/drift.test.ts.`,
|
|
22
|
+
``,
|
|
23
|
+
`export const ${name} = {`,
|
|
24
|
+
` whenToUse: ${lit(whenToUse)},`,
|
|
25
|
+
` whenNotToUse: ${lit(whenNotToUse)},`,
|
|
26
|
+
` gotchas: [`,
|
|
27
|
+
...gotchas.map((g) => ` ${lit(g)},`),
|
|
28
|
+
` ],`,
|
|
29
|
+
` variants: [${variants.map((v) => lit(v)).join(", ")}] as string[],`,
|
|
30
|
+
`};`,
|
|
31
|
+
``
|
|
32
|
+
].join("\n");
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
componentSlugs,
|
|
36
|
+
renderComponentMeta
|
|
37
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const UPSTREAM_PROVENANCE_ROOTS = [
|
|
2
|
+
// Video projects that stayed in remotion-videos.
|
|
3
|
+
"revola-video",
|
|
4
|
+
"expanse-video",
|
|
5
|
+
"qse-video",
|
|
6
|
+
"act854-video",
|
|
7
|
+
"datapeak-video",
|
|
8
|
+
"klaviyo-segments-video",
|
|
9
|
+
"qpa-video",
|
|
10
|
+
"reverence-video",
|
|
11
|
+
"enjamb-teaser",
|
|
12
|
+
"workday-harness-video",
|
|
13
|
+
"rcp-fund7-video",
|
|
14
|
+
// Pre-split working documents that stayed with the video projects.
|
|
15
|
+
"claude-sessions-digest"
|
|
16
|
+
];
|
|
17
|
+
const UPSTREAM_ISSUE_PREFIX = "remotion-videos-";
|
|
18
|
+
function isUpstreamIssue(id) {
|
|
19
|
+
return id.startsWith(UPSTREAM_ISSUE_PREFIX);
|
|
20
|
+
}
|
|
21
|
+
function isUpstreamProvenance(path) {
|
|
22
|
+
return UPSTREAM_PROVENANCE_ROOTS.some(
|
|
23
|
+
(root) => path === root || path.startsWith(`${root}/`)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function upstreamCitationError(path) {
|
|
27
|
+
if (path.includes("\\")) return "contains a backslash";
|
|
28
|
+
const segments = path.split("/");
|
|
29
|
+
if (segments.some((s) => s === "")) return "has an empty path segment";
|
|
30
|
+
if (segments.some((s) => s === "." || s === "..")) {
|
|
31
|
+
return "contains a relative segment";
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
UPSTREAM_ISSUE_PREFIX,
|
|
37
|
+
UPSTREAM_PROVENANCE_ROOTS,
|
|
38
|
+
isUpstreamIssue,
|
|
39
|
+
isUpstreamProvenance,
|
|
40
|
+
upstreamCitationError
|
|
41
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[
|
|
2
|
+
"alignment-group",
|
|
3
|
+
"attachment-offset",
|
|
4
|
+
"band-breach",
|
|
5
|
+
"blank-region-hold",
|
|
6
|
+
"brand-provenance",
|
|
7
|
+
"brief-structure",
|
|
8
|
+
"case-system",
|
|
9
|
+
"contract-satisfiable",
|
|
10
|
+
"copy-tracks-the-read",
|
|
11
|
+
"crowding-legibility",
|
|
12
|
+
"dead-frame-at-cut",
|
|
13
|
+
"edge-touch",
|
|
14
|
+
"fade-stack-at-cut",
|
|
15
|
+
"frame-count",
|
|
16
|
+
"group-member-count",
|
|
17
|
+
"hero-regression",
|
|
18
|
+
"hero-size",
|
|
19
|
+
"loudness",
|
|
20
|
+
"occlusion",
|
|
21
|
+
"placeholder-content",
|
|
22
|
+
"rebanding-conflict",
|
|
23
|
+
"scene-serves-thesis",
|
|
24
|
+
"seam-continuity",
|
|
25
|
+
"seam-fidelity",
|
|
26
|
+
"sibling-overlap",
|
|
27
|
+
"snap",
|
|
28
|
+
"static-hold",
|
|
29
|
+
"tag-coverage",
|
|
30
|
+
"text-fit",
|
|
31
|
+
"thesis-fidelity",
|
|
32
|
+
"viz-declared",
|
|
33
|
+
"vo-element-sync"
|
|
34
|
+
]
|