@vibeframe/cli 0.52.1 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/agent/tools/index.d.ts +1 -0
- package/dist/agent/tools/index.d.ts.map +1 -1
- package/dist/agent/tools/index.js +3 -0
- package/dist/agent/tools/index.js.map +1 -1
- package/dist/agent/tools/scene.d.ts +17 -0
- package/dist/agent/tools/scene.d.ts.map +1 -0
- package/dist/agent/tools/scene.js +263 -0
- package/dist/agent/tools/scene.js.map +1 -0
- package/dist/agent/tools/scene.test.d.ts +2 -0
- package/dist/agent/tools/scene.test.d.ts.map +1 -0
- package/dist/agent/tools/scene.test.js +139 -0
- package/dist/agent/tools/scene.test.js.map +1 -0
- package/dist/commands/_shared/scene-html-emit.d.ts +120 -0
- package/dist/commands/_shared/scene-html-emit.d.ts.map +1 -0
- package/dist/commands/_shared/scene-html-emit.js +422 -0
- package/dist/commands/_shared/scene-html-emit.js.map +1 -0
- package/dist/commands/_shared/scene-html-emit.test.d.ts +2 -0
- package/dist/commands/_shared/scene-html-emit.test.d.ts.map +1 -0
- package/dist/commands/_shared/scene-html-emit.test.js +396 -0
- package/dist/commands/_shared/scene-html-emit.test.js.map +1 -0
- package/dist/commands/_shared/scene-lint.d.ts +110 -0
- package/dist/commands/_shared/scene-lint.d.ts.map +1 -0
- package/dist/commands/_shared/scene-lint.js +207 -0
- package/dist/commands/_shared/scene-lint.js.map +1 -0
- package/dist/commands/_shared/scene-lint.test.d.ts +2 -0
- package/dist/commands/_shared/scene-lint.test.d.ts.map +1 -0
- package/dist/commands/_shared/scene-lint.test.js +208 -0
- package/dist/commands/_shared/scene-lint.test.js.map +1 -0
- package/dist/commands/_shared/scene-project.d.ts +101 -0
- package/dist/commands/_shared/scene-project.d.ts.map +1 -0
- package/dist/commands/_shared/scene-project.js +281 -0
- package/dist/commands/_shared/scene-project.js.map +1 -0
- package/dist/commands/_shared/scene-project.test.d.ts +2 -0
- package/dist/commands/_shared/scene-project.test.d.ts.map +1 -0
- package/dist/commands/_shared/scene-project.test.js +203 -0
- package/dist/commands/_shared/scene-project.test.js.map +1 -0
- package/dist/commands/_shared/scene-render.d.ts +79 -0
- package/dist/commands/_shared/scene-render.d.ts.map +1 -0
- package/dist/commands/_shared/scene-render.js +138 -0
- package/dist/commands/_shared/scene-render.js.map +1 -0
- package/dist/commands/_shared/scene-render.test.d.ts +2 -0
- package/dist/commands/_shared/scene-render.test.d.ts.map +1 -0
- package/dist/commands/_shared/scene-render.test.js +145 -0
- package/dist/commands/_shared/scene-render.test.js.map +1 -0
- package/dist/commands/_shared/segments-to-scenes.d.ts +85 -0
- package/dist/commands/_shared/segments-to-scenes.d.ts.map +1 -0
- package/dist/commands/_shared/segments-to-scenes.js +202 -0
- package/dist/commands/_shared/segments-to-scenes.js.map +1 -0
- package/dist/commands/_shared/segments-to-scenes.test.d.ts +2 -0
- package/dist/commands/_shared/segments-to-scenes.test.d.ts.map +1 -0
- package/dist/commands/_shared/segments-to-scenes.test.js +219 -0
- package/dist/commands/_shared/segments-to-scenes.test.js.map +1 -0
- package/dist/commands/_shared/tts-resolve.d.ts +75 -0
- package/dist/commands/_shared/tts-resolve.d.ts.map +1 -0
- package/dist/commands/_shared/tts-resolve.js +89 -0
- package/dist/commands/_shared/tts-resolve.js.map +1 -0
- package/dist/commands/_shared/tts-resolve.test.d.ts +6 -0
- package/dist/commands/_shared/tts-resolve.test.d.ts.map +1 -0
- package/dist/commands/_shared/tts-resolve.test.js +147 -0
- package/dist/commands/_shared/tts-resolve.test.js.map +1 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts.map +1 -1
- package/dist/commands/ai-script-pipeline-cli.js +49 -0
- package/dist/commands/ai-script-pipeline-cli.js.map +1 -1
- package/dist/commands/ai-script-pipeline.d.ts +16 -0
- package/dist/commands/ai-script-pipeline.d.ts.map +1 -1
- package/dist/commands/ai-script-pipeline.js +28 -0
- package/dist/commands/ai-script-pipeline.js.map +1 -1
- package/dist/commands/ai.test.js +4 -1
- package/dist/commands/ai.test.js.map +1 -1
- package/dist/commands/scene.d.ts +86 -0
- package/dist/commands/scene.d.ts.map +1 -0
- package/dist/commands/scene.js +719 -0
- package/dist/commands/scene.js.map +1 -0
- package/dist/commands/scene.test.d.ts +2 -0
- package/dist/commands/scene.test.d.ts.map +1 -0
- package/dist/commands/scene.test.js +219 -0
- package/dist/commands/scene.test.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/renderers/chrome.d.ts +26 -0
- package/dist/pipeline/renderers/chrome.d.ts.map +1 -0
- package/dist/pipeline/renderers/chrome.js +48 -0
- package/dist/pipeline/renderers/chrome.js.map +1 -0
- package/dist/pipeline/renderers/hyperframes.d.ts.map +1 -1
- package/dist/pipeline/renderers/hyperframes.js +2 -32
- package/dist/pipeline/renderers/hyperframes.js.map +1 -1
- package/dist/utils/provider-resolver.d.ts.map +1 -1
- package/dist/utils/provider-resolver.js +6 -2
- package/dist/utils/provider-resolver.js.map +1 -1
- package/package.json +32 -13
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module _shared/scene-lint
|
|
3
|
+
*
|
|
4
|
+
* In-process Hyperframes lint pipeline for VibeFrame scene projects. Wraps
|
|
5
|
+
* `runHyperframeLint` from `@hyperframes/producer` (its public lint entry
|
|
6
|
+
* point) and adapts the output to VibeFrame's two-tier file structure:
|
|
7
|
+
*
|
|
8
|
+
* project/
|
|
9
|
+
* index.html # root composition → linted as-is
|
|
10
|
+
* compositions/*.html # sub-compositions → producer's lint emits two
|
|
11
|
+
* spurious findings here, so
|
|
12
|
+
* we filter them out.
|
|
13
|
+
*
|
|
14
|
+
* Two findings are filtered for sub-compositions because they encode the
|
|
15
|
+
* inverse rule (sub-comps SHOULD be wrapped in `<template>` and SHOULD NOT
|
|
16
|
+
* have an `<html>` wrapper):
|
|
17
|
+
* - `standalone_composition_wrapped_in_template`
|
|
18
|
+
* - `root_composition_missing_html_wrapper`
|
|
19
|
+
*
|
|
20
|
+
* Pure helpers are exported for unit testing; `runProjectLint` does the
|
|
21
|
+
* filesystem walk + lint orchestration. Mechanical `--fix` is intentionally
|
|
22
|
+
* conservative — only `timed_element_missing_clip_class` is auto-fixed in
|
|
23
|
+
* MVP 1.
|
|
24
|
+
*/
|
|
25
|
+
import { readdir, readFile, writeFile, stat } from "node:fs/promises";
|
|
26
|
+
import { existsSync } from "node:fs";
|
|
27
|
+
import { resolve, relative, join } from "node:path";
|
|
28
|
+
import { runHyperframeLint, } from "@hyperframes/producer";
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Pure helpers
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/** Producer's two findings that are inverse-rules for sub-compositions. */
|
|
33
|
+
export const SUB_COMP_FALSE_POSITIVES = new Set([
|
|
34
|
+
"standalone_composition_wrapped_in_template",
|
|
35
|
+
"root_composition_missing_html_wrapper",
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Discover scene files in a project. Returns the root composition (or null
|
|
39
|
+
* if missing) plus every `*.html` file under `compositions/` recursively.
|
|
40
|
+
*
|
|
41
|
+
* Paths returned are absolute. The caller derives project-relative paths via
|
|
42
|
+
* `relative(projectDir, path)`.
|
|
43
|
+
*/
|
|
44
|
+
export async function discoverSceneFiles(opts) {
|
|
45
|
+
const projectDir = resolve(opts.projectDir);
|
|
46
|
+
const rootAbs = resolve(projectDir, opts.rootRel ?? "index.html");
|
|
47
|
+
const root = existsSync(rootAbs) ? rootAbs : null;
|
|
48
|
+
const compsDir = resolve(projectDir, "compositions");
|
|
49
|
+
const subs = [];
|
|
50
|
+
if (existsSync(compsDir)) {
|
|
51
|
+
await collectHtmlRecursive(compsDir, subs);
|
|
52
|
+
subs.sort();
|
|
53
|
+
}
|
|
54
|
+
return { root, subs };
|
|
55
|
+
}
|
|
56
|
+
async function collectHtmlRecursive(dir, into) {
|
|
57
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const full = join(dir, entry.name);
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
await collectHtmlRecursive(full, into);
|
|
62
|
+
}
|
|
63
|
+
else if (entry.isFile() && entry.name.toLowerCase().endsWith(".html")) {
|
|
64
|
+
into.push(full);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Drop findings that producer's lint emits as inverse-rules for sub-comp
|
|
70
|
+
* files. Other findings pass through unchanged.
|
|
71
|
+
*/
|
|
72
|
+
export function filterSubCompFalsePositives(findings, isSubComposition) {
|
|
73
|
+
if (!isSubComposition)
|
|
74
|
+
return findings;
|
|
75
|
+
return findings.filter((f) => !SUB_COMP_FALSE_POSITIVES.has(f.code));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Apply mechanical `--fix` rewrites for known-safe finding codes. Returns the
|
|
79
|
+
* (possibly unchanged) HTML and the list of codes that were fixed at least
|
|
80
|
+
* once.
|
|
81
|
+
*
|
|
82
|
+
* MVP 1 only auto-fixes `timed_element_missing_clip_class` — adding the
|
|
83
|
+
* `clip` class to elements that already carry timing attributes.
|
|
84
|
+
*
|
|
85
|
+
* Other "registration"/"paused" fixes are intentionally NOT mechanical —
|
|
86
|
+
* they require structural reasoning (where to insert the `window.__timelines`
|
|
87
|
+
* block, how to convert an unpaused timeline) that goes beyond a regex.
|
|
88
|
+
* The lint output still surfaces them with `fixHint` for the agent or human
|
|
89
|
+
* to apply.
|
|
90
|
+
*/
|
|
91
|
+
export function applyMechanicalFixes(html, findings) {
|
|
92
|
+
const fixedCodes = new Set();
|
|
93
|
+
let updated = html;
|
|
94
|
+
if (findings.some((f) => f.code === "timed_element_missing_clip_class")) {
|
|
95
|
+
const next = addClipClassToTimedElements(updated);
|
|
96
|
+
if (next !== updated) {
|
|
97
|
+
updated = next;
|
|
98
|
+
fixedCodes.add("timed_element_missing_clip_class");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { html: updated, fixedCodes: [...fixedCodes] };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Add `class="clip"` (or merge into an existing `class="..."`) on every
|
|
105
|
+
* element that has both `data-start` and `data-duration` but no `clip` class.
|
|
106
|
+
*
|
|
107
|
+
* Skips `<audio>` and `<video>` elements — those have timing attributes but
|
|
108
|
+
* use their own track-management semantics, and the lint rule already exempts
|
|
109
|
+
* them.
|
|
110
|
+
*/
|
|
111
|
+
function addClipClassToTimedElements(html) {
|
|
112
|
+
return html.replace(/<([a-z][a-z0-9-]*)([^>]*)>/gi, (full, tag, attrs) => {
|
|
113
|
+
const lower = tag.toLowerCase();
|
|
114
|
+
if (lower === "audio" || lower === "video")
|
|
115
|
+
return full;
|
|
116
|
+
if (!/\sdata-start="/.test(attrs))
|
|
117
|
+
return full;
|
|
118
|
+
if (!/\sdata-duration="/.test(attrs))
|
|
119
|
+
return full;
|
|
120
|
+
const classMatch = attrs.match(/\sclass="([^"]*)"/);
|
|
121
|
+
if (classMatch) {
|
|
122
|
+
const classes = classMatch[1].split(/\s+/).filter(Boolean);
|
|
123
|
+
if (classes.includes("clip"))
|
|
124
|
+
return full;
|
|
125
|
+
const merged = [...classes, "clip"].join(" ");
|
|
126
|
+
return `<${tag}${attrs.replace(/\sclass="[^"]*"/, ` class="${merged}"`)}>`;
|
|
127
|
+
}
|
|
128
|
+
return `<${tag} class="clip"${attrs}>`;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Walk the project, lint every HTML file, optionally apply mechanical fixes,
|
|
133
|
+
* and return aggregated counts. Throws only on FS errors; lint errors are
|
|
134
|
+
* surfaced as findings, not exceptions.
|
|
135
|
+
*/
|
|
136
|
+
export async function runProjectLint(opts) {
|
|
137
|
+
const projectDir = resolve(opts.projectDir);
|
|
138
|
+
const { root, subs } = await discoverSceneFiles({ projectDir, rootRel: opts.rootRel });
|
|
139
|
+
const files = [];
|
|
140
|
+
const fixed = [];
|
|
141
|
+
const targets = [];
|
|
142
|
+
if (root)
|
|
143
|
+
targets.push({ abs: root, isSub: false });
|
|
144
|
+
for (const sub of subs)
|
|
145
|
+
targets.push({ abs: sub, isSub: true });
|
|
146
|
+
for (const { abs, isSub } of targets) {
|
|
147
|
+
const rel = relative(projectDir, abs) || abs;
|
|
148
|
+
const html = await readFile(abs, "utf-8");
|
|
149
|
+
const prepared = {
|
|
150
|
+
html,
|
|
151
|
+
entryFile: rel,
|
|
152
|
+
source: "projectDir",
|
|
153
|
+
};
|
|
154
|
+
const raw = runHyperframeLint(prepared);
|
|
155
|
+
const findings = filterSubCompFalsePositives(raw.findings, isSub);
|
|
156
|
+
if (opts.fix && findings.length > 0) {
|
|
157
|
+
const { html: nextHtml, fixedCodes } = applyMechanicalFixes(html, findings);
|
|
158
|
+
if (fixedCodes.length > 0) {
|
|
159
|
+
await writeFile(abs, nextHtml, "utf-8");
|
|
160
|
+
fixed.push({ file: rel, codes: fixedCodes });
|
|
161
|
+
// Re-lint after fix so the result reflects what's left.
|
|
162
|
+
const reLinted = runHyperframeLint({ ...prepared, html: nextHtml });
|
|
163
|
+
files.push({
|
|
164
|
+
file: rel,
|
|
165
|
+
isSubComposition: isSub,
|
|
166
|
+
findings: filterSubCompFalsePositives(reLinted.findings, isSub),
|
|
167
|
+
});
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
files.push({ file: rel, isSubComposition: isSub, findings });
|
|
172
|
+
}
|
|
173
|
+
let errorCount = 0;
|
|
174
|
+
let warningCount = 0;
|
|
175
|
+
let infoCount = 0;
|
|
176
|
+
for (const f of files) {
|
|
177
|
+
for (const finding of f.findings) {
|
|
178
|
+
if (finding.severity === "error")
|
|
179
|
+
errorCount++;
|
|
180
|
+
else if (finding.severity === "warning")
|
|
181
|
+
warningCount++;
|
|
182
|
+
else
|
|
183
|
+
infoCount++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
ok: errorCount === 0,
|
|
188
|
+
errorCount,
|
|
189
|
+
warningCount,
|
|
190
|
+
infoCount,
|
|
191
|
+
files,
|
|
192
|
+
fixed,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/** True if `root` exists and is a regular file. Used by callers that want to
|
|
196
|
+
* pre-validate before invoking `runProjectLint`. */
|
|
197
|
+
export async function rootExists(projectDir, rootRel = "index.html") {
|
|
198
|
+
const abs = resolve(projectDir, rootRel);
|
|
199
|
+
try {
|
|
200
|
+
const s = await stat(abs);
|
|
201
|
+
return s.isFile();
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=scene-lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-lint.js","sourceRoot":"","sources":["../../../src/commands/_shared/scene-lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-lint.test.d.ts","sourceRoot":"","sources":["../../../src/commands/_shared/scene-lint.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { mkdtemp, mkdir, writeFile, readFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { applyMechanicalFixes, discoverSceneFiles, filterSubCompFalsePositives, rootExists, runProjectLint, SUB_COMP_FALSE_POSITIVES, } from "./scene-lint.js";
|
|
6
|
+
import { buildEmptyRootHtml, scaffoldSceneProject, } from "./scene-project.js";
|
|
7
|
+
import { buildClipReference, emitSceneHtml, insertClipIntoRoot, } from "./scene-html-emit.js";
|
|
8
|
+
async function makeTmp(label = "vibe-scene-lint-") {
|
|
9
|
+
return mkdtemp(join(tmpdir(), label));
|
|
10
|
+
}
|
|
11
|
+
// ── filterSubCompFalsePositives ─────────────────────────────────────────────
|
|
12
|
+
describe("filterSubCompFalsePositives", () => {
|
|
13
|
+
const findings = [
|
|
14
|
+
{ code: "standalone_composition_wrapped_in_template", severity: "warning", message: "x" },
|
|
15
|
+
{ code: "root_composition_missing_html_wrapper", severity: "warning", message: "x" },
|
|
16
|
+
{ code: "missing_timeline_registry", severity: "error", message: "real" },
|
|
17
|
+
];
|
|
18
|
+
it("drops the two known false positives for sub-compositions", () => {
|
|
19
|
+
const out = filterSubCompFalsePositives(findings, true);
|
|
20
|
+
expect(out).toHaveLength(1);
|
|
21
|
+
expect(out[0].code).toBe("missing_timeline_registry");
|
|
22
|
+
});
|
|
23
|
+
it("returns root-composition findings unchanged", () => {
|
|
24
|
+
const out = filterSubCompFalsePositives(findings, false);
|
|
25
|
+
expect(out).toHaveLength(3);
|
|
26
|
+
});
|
|
27
|
+
it("exposes the filtered codes via SUB_COMP_FALSE_POSITIVES", () => {
|
|
28
|
+
expect(SUB_COMP_FALSE_POSITIVES.has("standalone_composition_wrapped_in_template")).toBe(true);
|
|
29
|
+
expect(SUB_COMP_FALSE_POSITIVES.has("root_composition_missing_html_wrapper")).toBe(true);
|
|
30
|
+
expect(SUB_COMP_FALSE_POSITIVES.size).toBe(2);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
// ── applyMechanicalFixes ────────────────────────────────────────────────────
|
|
34
|
+
describe("applyMechanicalFixes — timed_element_missing_clip_class", () => {
|
|
35
|
+
const finding = {
|
|
36
|
+
code: "timed_element_missing_clip_class",
|
|
37
|
+
severity: "error",
|
|
38
|
+
message: "missing class=\"clip\"",
|
|
39
|
+
};
|
|
40
|
+
it("adds class=\"clip\" to elements with timing attributes and no class", () => {
|
|
41
|
+
const html = `<div data-start="0" data-duration="3" data-track-index="1">x</div>`;
|
|
42
|
+
const { html: out, fixedCodes } = applyMechanicalFixes(html, [finding]);
|
|
43
|
+
expect(out).toContain('<div class="clip" data-start="0" data-duration="3"');
|
|
44
|
+
expect(fixedCodes).toEqual(["timed_element_missing_clip_class"]);
|
|
45
|
+
});
|
|
46
|
+
it("merges into an existing class list rather than overwriting", () => {
|
|
47
|
+
const html = `<div class="card glow" data-start="0" data-duration="3" data-track-index="1">x</div>`;
|
|
48
|
+
const { html: out } = applyMechanicalFixes(html, [finding]);
|
|
49
|
+
expect(out).toContain('class="card glow clip"');
|
|
50
|
+
});
|
|
51
|
+
it("is idempotent — already-clipped elements aren't modified", () => {
|
|
52
|
+
const html = `<div class="clip card" data-start="0" data-duration="3" data-track-index="1">x</div>`;
|
|
53
|
+
const { html: out, fixedCodes } = applyMechanicalFixes(html, [finding]);
|
|
54
|
+
expect(out).toBe(html);
|
|
55
|
+
expect(fixedCodes).toEqual([]);
|
|
56
|
+
});
|
|
57
|
+
it("skips <audio> and <video> (their lint rule already exempts them)", () => {
|
|
58
|
+
const html = `<audio data-start="0" data-duration="3" src="x.mp3"></audio>
|
|
59
|
+
<video data-start="0" data-duration="3" src="x.mp4"></video>`;
|
|
60
|
+
const { html: out, fixedCodes } = applyMechanicalFixes(html, [finding]);
|
|
61
|
+
expect(out).toBe(html);
|
|
62
|
+
expect(fixedCodes).toEqual([]);
|
|
63
|
+
});
|
|
64
|
+
it("does not fix codes outside the auto-fix allow-list", () => {
|
|
65
|
+
const html = `<div data-start="0" data-duration="3">x</div>`;
|
|
66
|
+
const other = { code: "missing_timeline_registry", severity: "error", message: "x" };
|
|
67
|
+
const { html: out, fixedCodes } = applyMechanicalFixes(html, [other]);
|
|
68
|
+
expect(out).toBe(html);
|
|
69
|
+
expect(fixedCodes).toEqual([]);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
// ── discoverSceneFiles + rootExists ─────────────────────────────────────────
|
|
73
|
+
describe("discoverSceneFiles", () => {
|
|
74
|
+
it("returns null root when index.html is missing", async () => {
|
|
75
|
+
const dir = await makeTmp();
|
|
76
|
+
const out = await discoverSceneFiles({ projectDir: dir });
|
|
77
|
+
expect(out.root).toBeNull();
|
|
78
|
+
expect(out.subs).toEqual([]);
|
|
79
|
+
});
|
|
80
|
+
it("walks compositions/ recursively and sorts results", async () => {
|
|
81
|
+
const dir = await makeTmp();
|
|
82
|
+
await scaffoldSceneProject({ dir, name: "fix", aspect: "16:9", duration: 6 });
|
|
83
|
+
await mkdir(resolve(dir, "compositions/nested"), { recursive: true });
|
|
84
|
+
await writeFile(resolve(dir, "compositions/scene-b.html"), "x", "utf-8");
|
|
85
|
+
await writeFile(resolve(dir, "compositions/scene-a.html"), "x", "utf-8");
|
|
86
|
+
await writeFile(resolve(dir, "compositions/nested/deep.html"), "x", "utf-8");
|
|
87
|
+
await writeFile(resolve(dir, "compositions/notes.txt"), "ignored", "utf-8");
|
|
88
|
+
const out = await discoverSceneFiles({ projectDir: dir });
|
|
89
|
+
expect(out.root).toBe(resolve(dir, "index.html"));
|
|
90
|
+
expect(out.subs).toEqual([
|
|
91
|
+
resolve(dir, "compositions/nested/deep.html"),
|
|
92
|
+
resolve(dir, "compositions/scene-a.html"),
|
|
93
|
+
resolve(dir, "compositions/scene-b.html"),
|
|
94
|
+
]);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("rootExists", () => {
|
|
98
|
+
it("true when index.html exists, false otherwise", async () => {
|
|
99
|
+
const dir = await makeTmp();
|
|
100
|
+
expect(await rootExists(dir)).toBe(false);
|
|
101
|
+
await scaffoldSceneProject({ dir, name: "x", aspect: "16:9", duration: 4 });
|
|
102
|
+
expect(await rootExists(dir)).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
// ── runProjectLint — integration against scaffolded projects ────────────────
|
|
106
|
+
describe("runProjectLint — integration", () => {
|
|
107
|
+
async function scaffoldWithScenes() {
|
|
108
|
+
const dir = await makeTmp("vibe-lint-int-");
|
|
109
|
+
await scaffoldSceneProject({ dir, name: "fixture", aspect: "16:9", duration: 8 });
|
|
110
|
+
// Add two scenes by hand using the C2 emit helpers (avoids spawning the CLI).
|
|
111
|
+
let root = await readFile(resolve(dir, "index.html"), "utf-8");
|
|
112
|
+
const intro = emitSceneHtml({
|
|
113
|
+
id: "intro", preset: "announcement", width: 1920, height: 1080,
|
|
114
|
+
duration: 4, headline: "Hello",
|
|
115
|
+
});
|
|
116
|
+
await writeFile(resolve(dir, "compositions/scene-intro.html"), intro, "utf-8");
|
|
117
|
+
root = insertClipIntoRoot(root, { id: "intro", start: 0, duration: 4 });
|
|
118
|
+
const outro = emitSceneHtml({
|
|
119
|
+
id: "outro", preset: "simple", width: 1920, height: 1080,
|
|
120
|
+
duration: 3, subhead: "Thanks",
|
|
121
|
+
});
|
|
122
|
+
await writeFile(resolve(dir, "compositions/scene-outro.html"), outro, "utf-8");
|
|
123
|
+
root = insertClipIntoRoot(root, { id: "outro", start: 4, duration: 3 });
|
|
124
|
+
await writeFile(resolve(dir, "index.html"), root, "utf-8");
|
|
125
|
+
return dir;
|
|
126
|
+
}
|
|
127
|
+
it("produces ok=true on a freshly scaffolded project with valid scenes", async () => {
|
|
128
|
+
const dir = await scaffoldWithScenes();
|
|
129
|
+
const result = await runProjectLint({ projectDir: dir });
|
|
130
|
+
expect(result.ok).toBe(true);
|
|
131
|
+
expect(result.errorCount).toBe(0);
|
|
132
|
+
// 1 root + 2 sub-comps inspected
|
|
133
|
+
expect(result.files.map((f) => f.file).sort()).toEqual([
|
|
134
|
+
"compositions/scene-intro.html",
|
|
135
|
+
"compositions/scene-outro.html",
|
|
136
|
+
"index.html",
|
|
137
|
+
]);
|
|
138
|
+
// Sub-comp false positives must not appear
|
|
139
|
+
for (const file of result.files) {
|
|
140
|
+
for (const f of file.findings) {
|
|
141
|
+
expect(SUB_COMP_FALSE_POSITIVES.has(f.code)).toBe(false);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
it("flags a sub-comp that has timing attributes but no class=\"clip\"", async () => {
|
|
146
|
+
const dir = await scaffoldWithScenes();
|
|
147
|
+
// Mutate scene-intro.html: drop `class="clip"` from a timed element.
|
|
148
|
+
const broken = `<template id="bad-template">
|
|
149
|
+
<div data-composition-id="bad" data-start="0" data-duration="3" data-width="1920" data-height="1080">
|
|
150
|
+
<div data-start="0" data-duration="2" data-track-index="1">no class</div>
|
|
151
|
+
</div>
|
|
152
|
+
</template>`;
|
|
153
|
+
await writeFile(resolve(dir, "compositions/scene-bad.html"), broken, "utf-8");
|
|
154
|
+
const result = await runProjectLint({ projectDir: dir });
|
|
155
|
+
const badFile = result.files.find((f) => f.file.endsWith("scene-bad.html"));
|
|
156
|
+
expect(badFile).toBeDefined();
|
|
157
|
+
expect(badFile.findings.some((f) => f.code === "timed_element_missing_clip_class")).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
it("--fix repairs timed_element_missing_clip_class and re-lint shows it gone", async () => {
|
|
160
|
+
const dir = await scaffoldWithScenes();
|
|
161
|
+
const broken = `<template id="bad-template">
|
|
162
|
+
<div data-composition-id="bad" data-start="0" data-duration="3" data-width="1920" data-height="1080">
|
|
163
|
+
<div data-start="0" data-duration="2" data-track-index="1">no class</div>
|
|
164
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
|
165
|
+
<script>
|
|
166
|
+
window.__timelines = window.__timelines || {};
|
|
167
|
+
const tl = gsap.timeline({ paused: true });
|
|
168
|
+
window.__timelines["bad"] = tl;
|
|
169
|
+
</script>
|
|
170
|
+
</div>
|
|
171
|
+
</template>`;
|
|
172
|
+
const badPath = resolve(dir, "compositions/scene-bad.html");
|
|
173
|
+
await writeFile(badPath, broken, "utf-8");
|
|
174
|
+
const result = await runProjectLint({ projectDir: dir, fix: true });
|
|
175
|
+
// Fix tracked
|
|
176
|
+
const fix = result.fixed.find((f) => f.file.endsWith("scene-bad.html"));
|
|
177
|
+
expect(fix).toBeDefined();
|
|
178
|
+
expect(fix.codes).toContain("timed_element_missing_clip_class");
|
|
179
|
+
// File on disk is updated
|
|
180
|
+
const after = await readFile(badPath, "utf-8");
|
|
181
|
+
expect(after).toContain('<div class="clip" data-start="0" data-duration="2"');
|
|
182
|
+
// Re-lint result no longer reports it for that file
|
|
183
|
+
const badFile = result.files.find((f) => f.file.endsWith("scene-bad.html"));
|
|
184
|
+
expect(badFile.findings.some((f) => f.code === "timed_element_missing_clip_class")).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
it("returns ok=true and empty findings on an empty root with no compositions/ dir", async () => {
|
|
187
|
+
const dir = await makeTmp();
|
|
188
|
+
await writeFile(resolve(dir, "index.html"), buildEmptyRootHtml({ aspect: "16:9", duration: 5 }), "utf-8");
|
|
189
|
+
const result = await runProjectLint({ projectDir: dir });
|
|
190
|
+
expect(result.ok).toBe(true);
|
|
191
|
+
expect(result.files).toHaveLength(1);
|
|
192
|
+
expect(result.files[0].file).toBe("index.html");
|
|
193
|
+
});
|
|
194
|
+
it("does not flag a buildClipReference()-built clip in the root", async () => {
|
|
195
|
+
const dir = await scaffoldWithScenes();
|
|
196
|
+
// Produce one extra clip via the C2 helper just to be sure the produced
|
|
197
|
+
// markup keeps lint clean.
|
|
198
|
+
const root = await readFile(resolve(dir, "index.html"), "utf-8");
|
|
199
|
+
const augmented = root.replace("</div>\n\n <script>", ` ${buildClipReference({ id: "extra", start: 7, duration: 2 })}\n </div>\n\n <script>`);
|
|
200
|
+
await writeFile(resolve(dir, "index.html"), augmented, "utf-8");
|
|
201
|
+
// The extra clip references a non-existent composition file — that's a
|
|
202
|
+
// semantic/runtime concern, not a lint rule. So lint should still pass.
|
|
203
|
+
const result = await runProjectLint({ projectDir: dir });
|
|
204
|
+
const rootFile = result.files.find((f) => f.file === "index.html");
|
|
205
|
+
expect(rootFile.findings.some((f) => f.code === "timed_element_missing_clip_class")).toBe(false);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=scene-lint.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-lint.test.js","sourceRoot":"","sources":["../../../src/commands/_shared/scene-lint.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module _shared/scene-project
|
|
3
|
+
*
|
|
4
|
+
* Helpers for scaffolding a "scene project" — a directory that works as both
|
|
5
|
+
* a VibeFrame project (via `vibe.project.yaml`) AND a HeyGen Hyperframes
|
|
6
|
+
* project (via `hyperframes.json` + `meta.json` + `index.html`). Either
|
|
7
|
+
* toolchain can be run inside the directory.
|
|
8
|
+
*
|
|
9
|
+
* Pure functions; no I/O beyond `scaffoldSceneProject()` which orchestrates
|
|
10
|
+
* file writes. Everything else returns strings or JSON-serializable objects
|
|
11
|
+
* so it can be unit-tested without touching the filesystem.
|
|
12
|
+
*/
|
|
13
|
+
/** Supported aspect ratios for scene projects (maps to CSS canvas dims). */
|
|
14
|
+
export type SceneAspect = "16:9" | "9:16" | "1:1" | "4:5";
|
|
15
|
+
export declare function aspectToDims(aspect: SceneAspect): {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
/** Shape of the Hyperframes project config file. */
|
|
20
|
+
export interface HyperframesConfig {
|
|
21
|
+
$schema?: string;
|
|
22
|
+
registry?: string;
|
|
23
|
+
paths?: {
|
|
24
|
+
blocks?: string;
|
|
25
|
+
components?: string;
|
|
26
|
+
assets?: string;
|
|
27
|
+
};
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** Shape of the Hyperframes meta file. */
|
|
31
|
+
export interface HyperframesMeta {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** Shape of the new VibeFrame-specific project config. */
|
|
38
|
+
export interface VibeProjectConfig {
|
|
39
|
+
name: string;
|
|
40
|
+
aspect: SceneAspect;
|
|
41
|
+
/** Default scene duration in seconds when none is inferred from narration. */
|
|
42
|
+
defaultSceneDuration: number;
|
|
43
|
+
/** Default providers per capability. `null` means "auto-resolve from env". */
|
|
44
|
+
providers: {
|
|
45
|
+
image: "openai" | "gemini" | "grok" | null;
|
|
46
|
+
tts: "elevenlabs" | "kokoro" | null;
|
|
47
|
+
transcribe: "whisper" | null;
|
|
48
|
+
};
|
|
49
|
+
/** Cost ceiling for `vibe pipeline` runs in this project. 0 disables. */
|
|
50
|
+
budget: {
|
|
51
|
+
maxUsd: number;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Defaults for a fresh scene project. */
|
|
55
|
+
export declare function defaultVibeProjectConfig(name: string): VibeProjectConfig;
|
|
56
|
+
/** The Hyperframes config we write on init. Matches the format at
|
|
57
|
+
* hyperframe-learn/my-first-video/hyperframes.json.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildHyperframesConfig(): HyperframesConfig;
|
|
60
|
+
export declare function buildHyperframesMeta(name: string, now?: Date): HyperframesMeta;
|
|
61
|
+
/**
|
|
62
|
+
* Merge an existing Hyperframes config with our defaults, preserving any
|
|
63
|
+
* user-authored keys and nested values. `vibe scene init` is idempotent:
|
|
64
|
+
* running it on a directory that already has `hyperframes.json` must never
|
|
65
|
+
* lose user config.
|
|
66
|
+
*/
|
|
67
|
+
export declare function mergeHyperframesConfig(existing: HyperframesConfig, defaults: HyperframesConfig): HyperframesConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Minimal valid Hyperframes root composition — empty (no sub-compositions
|
|
70
|
+
* yet). A later `vibe scene add` inserts `<div class="clip" ...>` children.
|
|
71
|
+
*/
|
|
72
|
+
export declare function buildEmptyRootHtml(opts: {
|
|
73
|
+
aspect: SceneAspect;
|
|
74
|
+
duration: number;
|
|
75
|
+
}): string;
|
|
76
|
+
/** Project-local CLAUDE.md that orients an AI agent to both toolchains. */
|
|
77
|
+
export declare function buildProjectClaudeMd(name: string): string;
|
|
78
|
+
/** Minimal .gitignore for a scene project. */
|
|
79
|
+
export declare function buildSceneGitignore(): string;
|
|
80
|
+
export interface ScaffoldOptions {
|
|
81
|
+
dir: string;
|
|
82
|
+
name?: string;
|
|
83
|
+
aspect?: SceneAspect;
|
|
84
|
+
duration?: number;
|
|
85
|
+
now?: Date;
|
|
86
|
+
}
|
|
87
|
+
export interface ScaffoldResult {
|
|
88
|
+
/** Files written (absolute paths). */
|
|
89
|
+
created: string[];
|
|
90
|
+
/** Files that already existed and were NOT overwritten. */
|
|
91
|
+
skipped: string[];
|
|
92
|
+
/** Files that were merge-updated (currently only hyperframes.json). */
|
|
93
|
+
merged: string[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Scaffold (or update) a scene project at `dir`. Idempotent: running twice is
|
|
97
|
+
* a no-op; running on an existing Hyperframes project merges `hyperframes.json`
|
|
98
|
+
* instead of overwriting.
|
|
99
|
+
*/
|
|
100
|
+
export declare function scaffoldSceneProject(opts: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
101
|
+
//# sourceMappingURL=scene-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-project.d.ts","sourceRoot":"","sources":["../../../src/commands/_shared/scene-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAS1D,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAEnF;AAED,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,SAAS,EAAE;QACT,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAC;QAC3C,GAAG,EAAE,YAAY,GAAG,QAAQ,GAAG,IAAI,CAAC;QACpC,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;KAC9B,CAAC;IACF,yEAAyE;IACzE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5B;AAED,0CAA0C;AAC1C,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAQxE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,CAU1D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,eAAe,CAE1F;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,iBAAiB,GAC1B,iBAAiB,CAOnB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAyC1F;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgEzD;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,IAAI,MAAM,CAa5C;AAMD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uEAAuE;IACvE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAWD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA4EzF"}
|