@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/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
|
+
});
|
package/src/variants.ts
ADDED
|
@@ -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
|
+
}
|