fix(lint): promote rules to errors with registry exemptions and false-positive fixes (#1495)

* fix(lint): promote rules to errors with registry exemptions and false-positive fixes

- Export isRegistrySourceFile/isRegistryInstalledFile from composition.ts
- Add registry exemptions to google_fonts_import and font_family_without_font_face
- Add registry exemption to requestanimationframe_in_composition
- Fix timed_element_missing_clip_class: data-track-index alone no longer triggers
- Fix caption_transcript_parse_error: balanced-bracket scanner replaces non-greedy regex
- Fix missing_timeline_registry: skips sub-compositions and template-wrapped files
- Fix scene_layer_missing_visibility_kill: strip JS comments before pattern matching
- Fix gsap_css_transform_conflict: exempt from() alongside fromTo()
- Fix gsap_from_opacity_noop: only fires when opacity value is actually 0
- Add regression test for data-track-index-only elements

* test(lint): add regression tests for false-positive fixes

Covers the 7 missing negative-case assertions flagged in PR review:
- registry marker suppresses google_fonts_import + font_family_without_font_face
- registry marker suppresses requestanimationframe_in_composition
- isSubComposition suppresses missing_timeline_registry
- scene_layer_missing_visibility_kill: fires, commented-kill fires, real kill suppresses
- gsap_css_transform_conflict: from() exempt alongside fromTo()
- gsap_from_opacity_noop: non-zero opacity (e.g. 0.5) is a valid reveal, not a noop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(examples): fix warm-grain template to pass promoted lint rules

- index.html: remove undeclared "Lexend" from font-family stack
- intro.html: replace Google Fonts @import with bundled Inter font
- captions.html: quote TRANSCRIPT keys for valid JSON + use Inter font

Fixes CLI smoke CI failure after google_fonts_import, font_family_without_font_face,
and caption_transcript_parse_error were promoted from warning to error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(cli): resolve warm-grain from repo registry in dev mode + bundle at build

getStaticTemplateDir now falls back to registry/examples/<id> in dev mode
so CI smoke tests use the PR-branch copy instead of fetching from main.
build-copy.mjs copies warm-grain to dist/templates/warm-grain at build time
so packed CLIs can scaffold it offline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(examples): remove trailing comma from warm-grain TRANSCRIPT array

JSON.parse rejects trailing commas (valid JS, invalid JSON).
caption_transcript_parse_error was still firing because of the comma
on the last entry after quoting all keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-06-16 21:13:00 -07:00
committed by GitHub
co-authored by Claude Sonnet 4.6
parent cc7c206e9c
commit 386df23a74
17 changed files with 341 additions and 167 deletions
+7
View File
@@ -70,6 +70,13 @@ async function main() {
copyDir(join(CLI_ROOT, "src", "templates", tmpl), join(DIST, "templates", tmpl));
}
// Bundle warm-grain from the repo registry so the built CLI can scaffold it
// offline and CI smoke tests pick up PR-branch changes before merge to main.
const warmGrainSrc = join(REPO_ROOT, "registry", "examples", "warm-grain");
if (existsSync(warmGrainSrc)) {
copyDir(warmGrainSrc, join(DIST, "templates", "warm-grain"));
}
// Skills bundled into the published CLI. Branches don't all carry the same
// skills/ tree (it gets restructured), so each entry is existsSync-guarded:
// a missing skill dir warns + skips instead of crashing the build.
+9 -3
View File
@@ -182,10 +182,16 @@ function resolveAssetDir(devSegments: string[], builtSegments: string[]): string
// Resolves bundled templates shipped inside the CLI package
// (packages/cli/src/templates/<id> in dev, dist/templates/<id> when packed).
// Not to be confused with the repo-root registry/examples/ directory, which
// is fetched remotely via fetchRemoteTemplate.
// Dev-mode also checks registry/examples/<id> so that smoke CI tests pick up
// PR-branch template changes before the PR is merged to main.
function getStaticTemplateDir(templateId: string): string {
return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
const base = dirname(fileURLToPath(import.meta.url));
const devPath = resolve(base, "..", "templates", templateId);
if (existsSync(devPath)) return devPath;
// fallback: repo-root registry/examples/<id> (4 levels up from src/commands/)
const registryPath = resolve(base, "..", "..", "..", "..", "registry", "examples", templateId);
if (existsSync(registryPath)) return registryPath;
return resolve(base, "templates", templateId);
}
function getSharedTemplateDir(): string {