Skip to main content

hyperframes.lint

Wrap upstream's hyperframes lint as a structured pre-render diagnostic. Same input shape as hyperframes.render — pass project_artifact_key (a tarball from any upstream pack in the chain) or composition_html (a single-file index.html). Returns structured findings keyed by upstream's stable rule codes. Soft-surface by default (findings ARE the output); pass strict:true to gate downstream packs on a clean lint result.

hyperframes.scaffold → project tarball

hyperframes.interpolate → topic content

hyperframes.attach_audio → audio embedded

hyperframes.lint → ← THIS PACK: catch render-killers before render

hyperframes.render → MP4

Why this pack exists

During the v0.29.2→v0.29.3 investigation, a rendered MP4 showed only 2 distinct frames over 90 seconds despite the composition having rich content. The deepest diagnostic was already shipped — upstream's own hyperframes lint flagged the audio element as silent-in-renders (media_missing_id), the manual __timelines["x"] = tl registration as conflicting with the runtime's auto-discovery (gsap_studio_edit_blocked), and the Google Fonts <link> as fails-in-sandboxed-renders (google_fonts_import). All three contributed to the symptom.

Catching these BEFORE the render step saves wall-clock (renders take minutes; lint takes <1s) and surfaces fixable issues in a structured shape the agent or pipeline can act on. Upstream CLI takes precedence over custom Go: we wrap hyperframes lint --json rather than reimplementing its rule engine.

Input schema

FieldTypeRequiredDefaultNotes
project_artifact_keystringone-ofProject tarball from any upstream pack in the chain. Typical pipeline use.
composition_htmlstringone-ofSingle-file index.html. Useful for one-shot audits of an agent-authored composition. Pass EXACTLY ONE of project_artifact_key OR composition_html.
verbosebooleannofalseSurface info-level findings (hidden by the CLI default). Useful for thorough audits; most pipelines stay at default false.
strictbooleannofalseWhen true, any error-severity finding surfaces as CodeArtifactFailed. Use for CI / publish gates that should refuse to render if upstream's linter is unhappy.

Output schema

{
"lint": {
"ok": false,
"error_count": 2,
"warning_count": 19,
"info_count": 0,
"files_scanned": 2,
"findings": [
{
"code": "media_missing_id",
"severity": "error",
"message": "<audio> has data-start but no id attribute. The renderer requires id to discover media elements — this audio will be SILENT in renders.",
"fixHint": "Add a unique id attribute: <audio id=\"my-audio\" ...>",
"snippet": "<audio src=\"assets/aroll-audio.mp3\" data-start=\"0\"...",
"file": "/tmp/project/index.html"
}
]
},
"lint_artifact_key": "hyperframes.lint/abc123-lint.json"
}

Finding fields are passed through from upstream verbatim (camelCase preserved) so the rule codes / fix hints are stable across upstream version bumps. Top-level summary fields are snake_case to match the helmdeck pack-output convention.

Common findings + what to do

CodeSeverityOperator fix
media_missing_iderrorAdd id="x" to <audio>/<video> elements. Without it the renderer cannot discover them and they're silent in the MP4. helmdeck's hyperframes.attach_audio adds id="aroll-audio-<hash>" automatically since v0.29.4.
google_fonts_importerrorUse @font-face with locally-bundled .woff2 files. External font fetches fail in sandboxed renders (the bundled headless Chromium has restricted network access).
missing_gsap_scripterrorAdd <script src=".../gsap.min.js"> to the composition. The lint pack can detect this before the render fails.
gsap_studio_edit_blockedwarningDon't manually register window.__timelines["x"] = tl — the runtime does this automatically by reading data-composition-id. Manual registration conflicts with auto-discovery and triggers Studio edit-blocking.
composition_self_attribute_selectorwarningIn sub-composition CSS, use #decision-tree { ... } instead of [data-composition-id="decision-tree"] { ... }. The attribute selector leaks across sibling instances when a composition is embedded twice.
studio_missing_editable_idwarningAdd id="x" to any timeline-animated element you want Studio (the visual editor) to allow drag/resize on. Render-only pipelines can ignore this.

Examples

Pipeline-typical usage

After hyperframes.attach_audio returns, pass its project_artifact_key to lint, gate on clean result:

- pack: hyperframes.attach_audio
outputs:
- name: project_key
from: project_artifact_key
- pack: hyperframes.lint
inputs:
project_artifact_key: "${steps.attach_audio.project_key}"
strict: true # any error-severity finding aborts the pipeline

One-shot composition audit

When an agent authors a composition, lint it BEFORE uploading to the project tarball:

{
"pack": "hyperframes.lint",
"input": {
"composition_html": "<!doctype html><html>...</html>",
"verbose": true
}
}

Soft-surface (default — diagnostic only)

When you want findings as feedback without aborting downstream packs (most agent-debugging workflows):

{
"pack": "hyperframes.lint",
"input": {
"project_artifact_key": "scaffold-output-xyz"
}
}

The findings come back in the output; the pack returns success even with errors.

Strict mode error shape

When strict:true and any error-severity finding is present, the pack returns a typed CodeArtifactFailed error with the first finding's code + message inlined:

hyperframes.lint: 2 error-severity finding(s) in strict mode (warnings=19, info=0).
First: [media_missing_id] <audio> has data-start but no id attribute...

The partial output (with the full findings array) is still attached to the error so a calling agent can read both error.message AND output.lint.findings for full diagnostic context.