Skip to content

fix(cli): previews and every per-user cache follow HYPERFRAMES_CACHE_DIR - #7224

Merged
miguel-heygen merged 8 commits into
mainfrom
fix/cli-preview-session-cache-dir
Nov 5, 2026
Merged

miguel-heygen merged 8 commits into
mainfrom
fix/cli-preview-session-cache-dir

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

What

When HYPERFRAMES_CACHE_DIR is set, everything the CLI keeps as a per-user cache goes there. Before, five writers ignored it:

  • the background preview's session record and log (XDG_STATE_HOME, else %LOCALAPPDATA% on Windows, else ~/.local/state)
  • the registry's manifest cache (~/.hyperframes/cache)
  • the local search model (~/.hyperframes/models)
  • the catalog vectors, which two readers share (~/.hyperframes/catalog)
  • the records of what an app already showed (%LOCALAPPDATA%\hyperframes\catch-up, else ~/.hyperframes/catch-up)

Without HYPERFRAMES_CACHE_DIR, every path stays where it was, so nobody's existing downloads are orphaned.

Why

A Windows report: under an agent sandbox that only allows writes inside the workspace, the default cache folder failed with EPERM. Setting HYPERFRAMES_CACHE_DIR to a workspace folder fixed renders, but "managed preview remained unavailable": preview --background still wrote to %LOCALAPPDATA%\hyperframes\previews and failed with EPERM there. A search of the packages for writes under the home folder, %LOCALAPPDATA% and the XDG folders found the other four cache writers, each the next EPERM under the same sandbox.

Related work

#6716 moved the paths built as ~/.cache/hyperframes onto HYPERFRAMES_CACHE_DIR. These five were built from other folders, so that change and its "every cache path goes through hyperframesCacheDir" test did not catch them.

How

namedCacheDir(...parts) in @hyperframes/core/cache-dir returns a folder in the cache only when HYPERFRAMES_CACHE_DIR is set, and each writer falls back to its own default otherwise. The preview's defaultStateHome() returns <cache>/state, so the record lands in <cache>/state/hyperframes/previews. The registry cache goes to <cache>/registry, the model to <cache>/models, the catalog to <cache>/catalog (HYPERFRAMES_CATALOG_ARTIFACT_DIR still wins) and the catch-up records to <cache>/catch-up. Path constants read at import became functions, so the variable is read on each call.

media-use/lib/local-media-search.mjs reads the variable itself, with the same rule. That file is copied into dist as plain .mjs and run on its own, and @hyperframes/core is only bundled into the CLI, so it cannot import the helper.

The CLI's test setup (scripts/test-home.mjs) now clears HYPERFRAMES_CACHE_DIR with the other per-user folders. With it set in the shell and not cleared, the existing "keeps its records under LOCALAPPDATA on Windows" test fails, and tests would write into that folder.

Left alone on purpose:

  • The warm check's folder stays under %LOCALAPPDATA% on Windows and XDG_RUNTIME_DIR on Linux. It holds the token that authenticates the warm check server. On Windows the folder's owner is not checked, so a HYPERFRAMES_CACHE_DIR shared across accounts, as the render-slot docs suggest, would expose it. Under the sandbox its folder fails quietly and check runs cold.
  • Settings under ~/.hyperframes (telemetry, update checks, project links, the running-CLI record) are configuration, not cache. They belong with HYPERFRAMES_CONFIG_DIR, in a separate change.

Test plan

  • Unit tests added/updated: one test per writer sets HYPERFRAMES_CACHE_DIR and finds the path in the cache: previewLifecycle.test.ts (writes a session, state folder left empty), remote.test.ts (a fetched manifest lands in <cache>/registry), localModel.test.ts (model and tokenizer paths), localSemantic.test.ts (hasLocalVectors() reads <cache>/catalog), local-media-search.test.mjs (mediaVectorRows() reads it too) and appHistory.test.ts (the seen record is written under <cache>/catch-up). cacheDir.test.ts covers namedCacheDir. Each writer's own test fails when that file's old version is put back, and nothing else does.
    • fails without the fix: previewLifecycle.test.ts "where a preview's session is kept > is under HYPERFRAMES_CACHE_DIR when it is set, not the state folder" (expected false to be true); likewise remote.test.ts "caches manifests under HYPERFRAMES_CACHE_DIR when it is set" and appHistory.test.ts "keeps the seen record in the cache folder when it is set".
    • fails without the fix: localSemantic.test.ts "an empty HYPERFRAMES_CATALOG_ARTIFACT_DIR > counts as unset, as media search reads it". The two readers of the catalog disagreed on an empty value (?? against ||), so they could read different folders; both now treat it as unset.
    • The touched files' tests (167, plus the node test and core's 4) pass three runs in a row.
  • Manual testing performed: on windows-latest, with deny ACLs on %USERPROFILE%\.cache\hyperframes and %LOCALAPPDATA%\hyperframes standing in for the sandbox and HYPERFRAMES_CACHE_DIR set to a project folder. Published 0.9.15: render with the default cache fails EPERM: operation not permitted, scandir '...\.cache\hyperframes'. With the project cache, render exits 0, but preview --background fails EPERM: operation not permitted, mkdir '...\AppData\Local\hyperframes\previews'. This branch: preview --background exits 0 in background mode with its log at <project>\.hfcache\state\hyperframes\previews\…, and --status and --stop find it. The other four writers are proven by their unit tests only.
  • Documentation updated (if applicable): docs/packages/cli.mdx "Keep the environment healthy" lists what follows HYPERFRAMES_CACHE_DIR.
  • Comments follow CONTRIBUTING.md "Comments": no comments added.

Size

About 50 lines of source across six call sites and the helper, about 90 of tests, one test-setup line and a docs sentence. One fix: the cache variable covers every cache writer.

@mintlify

mintlify Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Nov 5, 2026, 10:16 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 113 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (8)

Unstable (1)

  • seqrotatenudge-none-pct-r0-root-z100: tracking 0.03, pressJump 0, drop 0, reload 3.03, render 0.04, renderKey -, undo false, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.08, renderKey -, undo true, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.08, renderKey -, undo true, teleport true

@miguel-heygen miguel-heygen changed the title fix(cli): a background preview follows HYPERFRAMES_CACHE_DIR fix(cli): previews and every per-user cache follow HYPERFRAMES_CACHE_DIR Nov 5, 2026

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes at 40049e8e. The only thing to fix is the description. The code is ready to approve.

Blocker (lane rule): the body has no fails without the fix: line that names a test. The closest line is "Each writer's own test fails without the fix: putting back that file's old version fails exactly its new test". It doesn't name a test. Please add a line for the headline Windows preview EPERM, for example:

fails without the fix: "where a preview's session is kept > is under HYPERFRAMES_CACHE_DIR when it is set, not the state folder"

What I checked at this head:

  • The touched CLI tests (previewLifecycle, localModel, localSemantic, remote, appHistory) pass: 166/166. The local-media-search.test.mjs node test passes, and core's cacheDir.test.ts passes 4/4. That matches the counts in the description.
  • Fails without the fix, confirmed for three writers. With the merge-base versions of previewLifecycle.ts, remote.ts and appHistory.ts put back, exactly these new tests fail and nothing else does:
    • "is under HYPERFRAMES_CACHE_DIR when it is set, not the state folder"
    • "caches manifests under HYPERFRAMES_CACHE_DIR when it is set"
    • "keeps the seen record in the cache folder when it is set"
  • Without the variable, nothing moves. namedCacheDir returns undefined and each writer falls back to its old path, so nobody's existing downloads are orphaned.
  • A shared-folder trust concern doesn't apply here. The cache already holds browser binaries and whisper/TTS models, so adding the manifest cache and the ONNX model doesn't widen what a shared HYPERFRAMES_CACHE_DIR must be trusted with. Leaving the warm-check token out is the right call.

Non-blocking nit:

  • localSemantic.ts uses ?? on HYPERFRAMES_CATALOG_ARTIFACT_DIR, while local-media-search.mjs uses ||. So an empty HYPERFRAMES_CATALOG_ARTIFACT_DIR= sends the two readers of the same vectors to different folders. This predates the PR.

Once the line is in the body I'll approve this head. No code change is needed.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at 70bff4a1. Both points from my change request are resolved.

  • The fails without the fix: lines are in the body. They name the preview, registry, catch-up and catalog tests.
  • The empty HYPERFRAMES_CATALOG_ARTIFACT_DIR nit is fixed. localSemantic.ts now uses ||, the same rule as local-media-search.mjs.
  • The new test fails without the fix: confirmed. With localSemantic.ts from the previous commit, "an empty HYPERFRAMES_CATALOG_ARTIFACT_DIR > counts as unset, as media search reads it" fails. At the head, localSemantic.test.ts passes 29/29.
  • Nothing else changed. Compared against its merge-base, the PR's patch is identical to 40049e8e, which I reviewed, apart from this change and its test. The rest of the diff between the two heads is the rebase onto main.

CI: the cancelled CI, PR captures and Windows render verification runs on this head are duplicates that concurrency superseded. The red CI / Test is that cancelled run's change-detection gate. The live CI, regression and Windows runs were still in progress when I approved.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit ecf0e14 Nov 5, 2026
177 of 219 checks passed
@miguel-heygen
miguel-heygen deleted the fix/cli-preview-session-cache-dir branch November 5, 2026 11:13
@heygengenesis heygengenesis Bot mentioned this pull request Nov 5, 2026
mitanshu450 pushed a commit to mitanshu450/hyperframes-video-generation that referenced this pull request Nov 5, 2026
* chore: release v0.9.16

* chore: format v0.9.16 release notes

* chore: add heygen-com#7228 and heygen-com#7231 to v0.9.16 notes

* chore: add heygen-com#7217 heygen-com#7224 heygen-com#7225 heygen-com#7226 heygen-com#7229 heygen-com#7233 to v0.9.16 notes
SanHsien added a commit to SanHsien/hyperframes that referenced this pull request Nov 6, 2026
…eview

Adopts or partially adopts 11 groups: multi-worker tween replay behind
the timeline stand-in (heygen-com#7231), template entries in the shared compile
stage (heygen-com#7217), HYPERFRAMES_CACHE_DIR and HYPERFRAMES_CONFIG_DIR for
every per-user cache and settings file (heygen-com#7224, heygen-com#7229; HeyGen
credentials stay under HEYGEN_CONFIG_DIR), WebKit audio clock (heygen-com#7225),
packet-based video length (heygen-com#7233), HLG tone mapping (heygen-com#7234), fetch
network cause (heygen-com#7236), .hyperframesignore in lint (heygen-com#7239), info
--media (heygen-com#7235), lint priority (heygen-com#7244), check --budget (heygen-com#7245) and the
unknown-command answer (heygen-com#7247). bun.lock gains only the lint `ignore`
edge from heygen-com#7239, already resolved. Watermark advances to 0a6746e.

Co-authored-by: Jerrai <[email protected]>
Co-authored-by: Miguel Ángel <[email protected]>
Co-authored-by: WaterrrForever <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

This branch was successfully deployed

1 active deployment
staging - docs — 70bff4a1 Deployed Nov 5, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant