diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34d76b148d..20f1a9c4e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -545,6 +545,8 @@ jobs: - name: Verify standalone skill imports run: bun test scripts/check-skill-import-boundaries.test.mjs - name: Discover and run skills tests + env: + HYPERFRAMES_MEDIA_HOME_REQUIRED: "1" # We expand the test list via bash so the job fails loudly when the # matcher comes back empty, rather than silently no-op'ing (which # would defeat the whole point of this job). diff --git a/package.json b/package.json index b4a4cea62f..26fa57635f 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "knip": "knip", "test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/prune-fallow-audit-caches.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts", "typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json", - "test:skills": "node --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'", + "test:skills": "HYPERFRAMES_MEDIA_HOME_REQUIRED=1 node --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'", "generate:previews": "tsx scripts/generate-template-previews.ts", "generate:catalog-previews": "tsx scripts/generate-catalog-previews.ts", "package:codex-plugin": "node scripts/package-codex-plugin.mjs", diff --git a/packages/cli/src/media-use/lib/cache.mjs b/packages/cli/src/media-use/lib/cache.mjs index c7c7d6f714..adcc895d90 100644 --- a/packages/cli/src/media-use/lib/cache.mjs +++ b/packages/cli/src/media-use/lib/cache.mjs @@ -1,17 +1,15 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync } from "node:fs"; import { join, basename } from "node:path"; import { createHash } from "node:crypto"; -import { homedir } from "node:os"; import { readManifest, appendRecord, normalizePrompt } from "./manifest.mjs"; +import { globalMediaDir, mediaHome } from "./media-home.mjs"; + +export { globalMediaDir }; const SCHEMA_PREFIX = "mu-v1-"; const KEY_HEX_CHARS = 16; const COMPLETE_SENTINEL = ".hf-complete"; -export function globalMediaDir() { - return join(homedir(), ".media"); -} - export function contentHash(filePath) { const bytes = readFileSync(filePath); return createHash("sha256").update(bytes).digest("hex"); @@ -30,11 +28,11 @@ function markComplete(entryDir) { } // The manifest helpers append their own ".media" to the dir they get, so the -// global manifest must be addressed by HOME, not by globalMediaDir() — passing +// global manifest must be addressed by mediaHome(), not by globalMediaDir() — passing // the latter nested it at ~/.media/.media/manifest.jsonl, invisible to the // Studio /api/assets/global route (which reads the documented flat path). export function readGlobalManifest() { - return readManifest(homedir()); + return readManifest(mediaHome()); } // Resolve a content-sha (full or unambiguous prefix) to a reusable global-cache @@ -105,7 +103,7 @@ export function cachePut(filePath, record) { reusable: true, cached_path: dest, }; - appendRecord(homedir(), globalRecord); + appendRecord(mediaHome(), globalRecord); return { sha, cached_path: dest }; } diff --git a/packages/cli/src/media-use/lib/candidates.test.mjs b/packages/cli/src/media-use/lib/candidates.test.mjs index 972577b3c0..72dabb587f 100644 --- a/packages/cli/src/media-use/lib/candidates.test.mjs +++ b/packages/cli/src/media-use/lib/candidates.test.mjs @@ -6,13 +6,13 @@ import { tmpdir } from "node:os"; import { listCandidates, formatCandidates, CANDIDATE_CAP } from "./candidates.mjs"; import { findGlobalBySha } from "./cache.mjs"; -// candidates + findGlobalBySha are offline (no heygen), so we can override HOME +// candidates + findGlobalBySha are offline (no heygen), so we can point HYPERFRAMES_MEDIA_HOME // to a temp dir and seed a fake global ~/.media manifest deterministically. function sandbox() { const root = mkdtempSync(join(tmpdir(), "mu-cand-")); const project = join(root, "proj"); const home = join(root, "home"); - process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, project, home }; } function seedManifest(dir, records) { diff --git a/packages/cli/src/media-use/lib/manifest.test.mjs b/packages/cli/src/media-use/lib/manifest.test.mjs index 08e078ff27..7422ec36b0 100644 --- a/packages/cli/src/media-use/lib/manifest.test.mjs +++ b/packages/cli/src/media-use/lib/manifest.test.mjs @@ -34,6 +34,8 @@ import { promote, } from "./cache.mjs"; +process.env.HYPERFRAMES_MEDIA_HOME = mkdtempSync(join(tmpdir(), "mu-media-home-")); + let tmp; function setup() { diff --git a/packages/cli/src/media-use/lib/media-home.mjs b/packages/cli/src/media-use/lib/media-home.mjs new file mode 100644 index 0000000000..8a9128fd3b --- /dev/null +++ b/packages/cli/src/media-use/lib/media-home.mjs @@ -0,0 +1,20 @@ +import { homedir } from "node:os"; +import { join } from "node:path"; + +// The one owner of where the person's media library lives. This repo's test runs set +// HYPERFRAMES_MEDIA_HOME_REQUIRED, so a test that forgot HYPERFRAMES_MEDIA_HOME fails instead +// of writing fixtures into the media library apps list as the person's own files. +export function mediaHome() { + const override = process.env.HYPERFRAMES_MEDIA_HOME; + if (override) return override; + if (process.env.HYPERFRAMES_MEDIA_HOME_REQUIRED) { + throw new Error( + "media-use: a test reached the real ~/.media; set HYPERFRAMES_MEDIA_HOME to a temp dir", + ); + } + return homedir(); +} + +export function globalMediaDir() { + return join(mediaHome(), ".media"); +} diff --git a/packages/cli/src/media-use/lib/media-home.test.mjs b/packages/cli/src/media-use/lib/media-home.test.mjs new file mode 100644 index 0000000000..16169f118f --- /dev/null +++ b/packages/cli/src/media-use/lib/media-home.test.mjs @@ -0,0 +1,61 @@ +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { test } from "node:test"; + +import { cachePut } from "./cache.mjs"; +import { globalMediaDir } from "./media-home.mjs"; + +const HOME = mkdtempSync(join(tmpdir(), "media-home-")); +process.env.HYPERFRAMES_MEDIA_HOME = HOME; + +test("the global cache writes into the media home a test points it at", () => { + const work = mkdtempSync(join(tmpdir(), "media-home-src-")); + const file = join(work, "clip.wav"); + writeFileSync(file, "media-home regression bytes"); + cachePut(file, { id: "bgm_001", type: "bgm", provenance: { prompt: "media home probe" } }); + const manifest = join(HOME, ".media", "manifest.jsonl"); + assert.ok(existsSync(manifest), "the temp media home holds the global manifest"); + assert.match(readFileSync(manifest, "utf8"), /media home probe/); + assert.equal(globalMediaDir(), join(HOME, ".media")); +}); + +// A child process that resolves the media dir, with only the given media-home variables set. +function runProbe(env) { + const lib = new URL("./media-home.mjs", import.meta.url).href; + const childEnv = { ...process.env }; + delete childEnv.HYPERFRAMES_MEDIA_HOME; + delete childEnv.HYPERFRAMES_MEDIA_HOME_REQUIRED; + delete childEnv.NODE_TEST_CONTEXT; + const run = spawnSync( + process.execPath, + [ + "--input-type=module", + "-e", + `const m = await import(${JSON.stringify(lib)}); console.log("dir=" + m.globalMediaDir());`, + ], + { encoding: "utf8", env: { ...childEnv, ...env } }, + ); + return { status: run.status, output: `${run.stdout}${run.stderr}` }; +} + +test("a repo test run that never points the media home anywhere fails instead of writing", () => { + const { status, output } = runProbe({ HYPERFRAMES_MEDIA_HOME_REQUIRED: "1" }); + assert.notEqual(status, 0, output); + assert.match(output, /set HYPERFRAMES_MEDIA_HOME to a temp dir/); +}); + +// Node sets NODE_TEST_CONTEXT for every project's test runs, so another project whose own tests +// spawn this CLI must get the person's real library, not the guard. +test("another project's node --test run still resolves the real media home", () => { + const home = mkdtempSync(join(tmpdir(), "media-home-user-")); + const { status, output } = runProbe({ + HOME: home, + USERPROFILE: home, + NODE_TEST_CONTEXT: "child-v8", + }); + assert.equal(status, 0, output); + assert.ok(output.includes(`dir=${join(home, ".media")}`), output); +}); diff --git a/packages/cli/src/media-use/lib/misses.mjs b/packages/cli/src/media-use/lib/misses.mjs index 585bb96384..ff5873c0aa 100644 --- a/packages/cli/src/media-use/lib/misses.mjs +++ b/packages/cli/src/media-use/lib/misses.mjs @@ -1,19 +1,19 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs"; -import { homedir } from "node:os"; -import { join } from "node:path"; +import { dirname, join } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; const MISSES_FILE = "misses.jsonl"; function missesPath() { - return join(homedir(), ".media", MISSES_FILE); + return join(globalMediaDir(), MISSES_FILE); } export function recordMiss({ type, intent, provider_override, local_only }) { try { - const dir = join(homedir(), ".media"); - mkdirSync(dir, { recursive: true }); + const path = missesPath(); + mkdirSync(dirname(path), { recursive: true }); appendFileSync( - join(dir, MISSES_FILE), + path, JSON.stringify({ ts: new Date().toISOString(), type, diff --git a/packages/cli/src/media-use/lib/misses.test.mjs b/packages/cli/src/media-use/lib/misses.test.mjs index d9b2585662..e5286c069d 100644 --- a/packages/cli/src/media-use/lib/misses.test.mjs +++ b/packages/cli/src/media-use/lib/misses.test.mjs @@ -9,7 +9,7 @@ function sandbox() { const root = mkdtempSync(join(tmpdir(), "mu-misses-")); const home = join(root, "home"); mkdirSync(home, { recursive: true }); - process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, home }; } @@ -54,6 +54,17 @@ test("recordMiss swallows filesystem failures", () => { } }); +test("recordMiss stays best-effort when the media home cannot be resolved", () => { + const savedEnv = { ...process.env }; + delete process.env.HYPERFRAMES_MEDIA_HOME; + process.env.HYPERFRAMES_MEDIA_HOME_REQUIRED = "1"; + try { + assert.doesNotThrow(() => recordMiss({ type: "sfx", intent: "no home", local_only: true })); + } finally { + restoreEnv(savedEnv); + } +}); + test("readMisses skips corrupt lines", () => { const savedEnv = { ...process.env }; const { root, home } = sandbox(); diff --git a/packages/cli/src/media-use/lib/prefs-store.mjs b/packages/cli/src/media-use/lib/prefs-store.mjs index 6bc3f7345f..a8f8489697 100644 --- a/packages/cli/src/media-use/lib/prefs-store.mjs +++ b/packages/cli/src/media-use/lib/prefs-store.mjs @@ -1,6 +1,6 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs"; -import { homedir } from "node:os"; import { basename, dirname, join, resolve } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; /** * Remembered defaults — the lightweight tier of HyperFrames user memory. @@ -41,7 +41,7 @@ export function projectPrefsPath(projectDir) { } export function userPrefsPath() { - return join(homedir(), ".media", PREFS_FILE); + return join(globalMediaDir(), PREFS_FILE); } function emptyFile() { diff --git a/packages/cli/src/media-use/lib/prefs-store.test.mjs b/packages/cli/src/media-use/lib/prefs-store.test.mjs index e0bc5ca814..4c13e5fa24 100644 --- a/packages/cli/src/media-use/lib/prefs-store.test.mjs +++ b/packages/cli/src/media-use/lib/prefs-store.test.mjs @@ -19,7 +19,7 @@ function sandbox() { mkdirSync(home, { recursive: true }); mkdirSync(projectA, { recursive: true }); mkdirSync(projectB, { recursive: true }); - process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, home, projectA, projectB }; } diff --git a/packages/cli/src/media-use/lib/recipe-store.mjs b/packages/cli/src/media-use/lib/recipe-store.mjs index e11ec96a31..2b710e049e 100644 --- a/packages/cli/src/media-use/lib/recipe-store.mjs +++ b/packages/cli/src/media-use/lib/recipe-store.mjs @@ -8,8 +8,8 @@ import { rmSync, writeFileSync, } from "node:fs"; -import { homedir } from "node:os"; import { basename, join, resolve } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; import { appendRecord, mediaDir, nextId } from "./manifest.mjs"; import { regenerateIndex } from "./index-gen.mjs"; import { mergedPreferences } from "./prefs-store.mjs"; @@ -58,7 +58,7 @@ export function projectRecipesDir(projectDir) { } export function userRecipesDir() { - return join(homedir(), ".media", "recipes"); + return join(globalMediaDir(), "recipes"); } export function slugifyRecipeName(name) { diff --git a/packages/cli/src/media-use/lib/recipe-store.test.mjs b/packages/cli/src/media-use/lib/recipe-store.test.mjs index 954291293d..2bf751dca8 100644 --- a/packages/cli/src/media-use/lib/recipe-store.test.mjs +++ b/packages/cli/src/media-use/lib/recipe-store.test.mjs @@ -83,7 +83,7 @@ function sandbox() { mkdirSync(project, { recursive: true }); writeFileSync(join(project, "frame.md"), "# Frame spec\nbackground: #101014\n"); writeFileSync(join(project, "STORYBOARD.md"), STORYBOARD); - process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, home, project }; } diff --git a/packages/cli/src/media-use/lib/stats.test.mjs b/packages/cli/src/media-use/lib/stats.test.mjs index ff0b6b466e..3e5c32cfeb 100644 --- a/packages/cli/src/media-use/lib/stats.test.mjs +++ b/packages/cli/src/media-use/lib/stats.test.mjs @@ -11,7 +11,7 @@ function sandbox() { const projectDir = join(root, "project"); mkdirSync(home, { recursive: true }); mkdirSync(projectDir, { recursive: true }); - process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, home, projectDir }; } diff --git a/packages/cli/src/media-use/lib/telemetry.mjs b/packages/cli/src/media-use/lib/telemetry.mjs index cd2911f529..373a0d26fd 100644 --- a/packages/cli/src/media-use/lib/telemetry.mjs +++ b/packages/cli/src/media-use/lib/telemetry.mjs @@ -5,6 +5,7 @@ import { randomUUID } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; const POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx"; const POSTHOG_HOST = "https://us.i.posthog.com"; @@ -72,7 +73,7 @@ function writeSharedConfig(config) { // one — otherwise cross-surface continuity would start over on upgrade. function legacyMediaAnonId() { try { - const file = join(homedir(), ".media", "anon-id"); + const file = join(globalMediaDir(), "anon-id"); if (existsSync(file)) { const id = readFileSync(file, "utf8").trim(); if (id) return id; diff --git a/packages/cli/src/media-use/lib/telemetry.test.mjs b/packages/cli/src/media-use/lib/telemetry.test.mjs index 1a66d60f78..54b3924336 100644 --- a/packages/cli/src/media-use/lib/telemetry.test.mjs +++ b/packages/cli/src/media-use/lib/telemetry.test.mjs @@ -18,6 +18,7 @@ function sandbox() { const home = join(root, "home"); mkdirSync(home, { recursive: true }); process.env.HOME = home; + process.env.HYPERFRAMES_MEDIA_HOME = home; return { root, home }; } diff --git a/packages/cli/src/media-use/resolve.test.mjs b/packages/cli/src/media-use/resolve.test.mjs index e9a617e82e..c06007a32e 100644 --- a/packages/cli/src/media-use/resolve.test.mjs +++ b/packages/cli/src/media-use/resolve.test.mjs @@ -33,10 +33,14 @@ const CAN_TSX = spawnSync(process.execPath, ["--import", "tsx", "--input-type=module", "-e", "0"], { stdio: "ignore", }).status === 0; +process.env.HYPERFRAMES_MEDIA_HOME = mkdtempSync(join(tmpdir(), "mu-resolve-home-")); + let tmp; function setup() { tmp = mkdtempSync(join(tmpdir(), "mu-resolve-test-")); + // A fresh global cache per test, apart from the project so the two manifests never coincide. + process.env.HYPERFRAMES_MEDIA_HOME = mkdtempSync(join(tmpdir(), "mu-resolve-home-")); } function cleanup() { diff --git a/scripts/check-media-use-copy-parity.test.mjs b/scripts/check-media-use-copy-parity.test.mjs index b9a045ae06..a2704f6bee 100644 --- a/scripts/check-media-use-copy-parity.test.mjs +++ b/scripts/check-media-use-copy-parity.test.mjs @@ -15,6 +15,7 @@ export const MEDIA_USE_COPY_NAMES = [ "index-gen.mjs", "manifest.mjs", "media-fetch.mjs", + "media-home.mjs", "npx-sync.mjs", "parakeet-words.mjs", "prefs-store.mjs", diff --git a/skills-manifest.json b/skills-manifest.json index 22fb77b7a0..a43f7227d7 100644 --- a/skills-manifest.json +++ b/skills-manifest.json @@ -54,8 +54,8 @@ "files": 1 }, "media-use": { - "hash": "b35de041b87e763d", - "files": 98 + "hash": "7915441c22070c00", + "files": 99 }, "motion-graphics": { "hash": "ab9d2e9c205ce1b1", diff --git a/skills/media-use/scripts/compatibility.test.mjs b/skills/media-use/scripts/compatibility.test.mjs index 9b638a074a..7e5b2ac478 100644 --- a/skills/media-use/scripts/compatibility.test.mjs +++ b/skills/media-use/scripts/compatibility.test.mjs @@ -6,6 +6,8 @@ import { execFileSync } from "node:child_process"; import test from "node:test"; import { pathToFileURL } from "node:url"; +process.env.HYPERFRAMES_MEDIA_HOME = mkdtempSync(join(tmpdir(), "media-use-compat-home-")); + function run(scriptsDir, script, args) { return execFileSync(process.execPath, [join(scriptsDir, script), ...args], { encoding: "utf8", diff --git a/skills/media-use/scripts/lib/media-home.mjs b/skills/media-use/scripts/lib/media-home.mjs new file mode 100644 index 0000000000..8a9128fd3b --- /dev/null +++ b/skills/media-use/scripts/lib/media-home.mjs @@ -0,0 +1,20 @@ +import { homedir } from "node:os"; +import { join } from "node:path"; + +// The one owner of where the person's media library lives. This repo's test runs set +// HYPERFRAMES_MEDIA_HOME_REQUIRED, so a test that forgot HYPERFRAMES_MEDIA_HOME fails instead +// of writing fixtures into the media library apps list as the person's own files. +export function mediaHome() { + const override = process.env.HYPERFRAMES_MEDIA_HOME; + if (override) return override; + if (process.env.HYPERFRAMES_MEDIA_HOME_REQUIRED) { + throw new Error( + "media-use: a test reached the real ~/.media; set HYPERFRAMES_MEDIA_HOME to a temp dir", + ); + } + return homedir(); +} + +export function globalMediaDir() { + return join(mediaHome(), ".media"); +} diff --git a/skills/media-use/scripts/lib/prefs-store.mjs b/skills/media-use/scripts/lib/prefs-store.mjs index 6bc3f7345f..a8f8489697 100644 --- a/skills/media-use/scripts/lib/prefs-store.mjs +++ b/skills/media-use/scripts/lib/prefs-store.mjs @@ -1,6 +1,6 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs"; -import { homedir } from "node:os"; import { basename, dirname, join, resolve } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; /** * Remembered defaults — the lightweight tier of HyperFrames user memory. @@ -41,7 +41,7 @@ export function projectPrefsPath(projectDir) { } export function userPrefsPath() { - return join(homedir(), ".media", PREFS_FILE); + return join(globalMediaDir(), PREFS_FILE); } function emptyFile() { diff --git a/skills/media-use/scripts/lib/recipe-store.mjs b/skills/media-use/scripts/lib/recipe-store.mjs index e11ec96a31..2b710e049e 100644 --- a/skills/media-use/scripts/lib/recipe-store.mjs +++ b/skills/media-use/scripts/lib/recipe-store.mjs @@ -8,8 +8,8 @@ import { rmSync, writeFileSync, } from "node:fs"; -import { homedir } from "node:os"; import { basename, join, resolve } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; import { appendRecord, mediaDir, nextId } from "./manifest.mjs"; import { regenerateIndex } from "./index-gen.mjs"; import { mergedPreferences } from "./prefs-store.mjs"; @@ -58,7 +58,7 @@ export function projectRecipesDir(projectDir) { } export function userRecipesDir() { - return join(homedir(), ".media", "recipes"); + return join(globalMediaDir(), "recipes"); } export function slugifyRecipeName(name) { diff --git a/skills/media-use/scripts/lib/telemetry.mjs b/skills/media-use/scripts/lib/telemetry.mjs index cd2911f529..373a0d26fd 100644 --- a/skills/media-use/scripts/lib/telemetry.mjs +++ b/skills/media-use/scripts/lib/telemetry.mjs @@ -5,6 +5,7 @@ import { randomUUID } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; +import { globalMediaDir } from "./media-home.mjs"; const POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx"; const POSTHOG_HOST = "https://us.i.posthog.com"; @@ -72,7 +73,7 @@ function writeSharedConfig(config) { // one — otherwise cross-surface continuity would start over on upgrade. function legacyMediaAnonId() { try { - const file = join(homedir(), ".media", "anon-id"); + const file = join(globalMediaDir(), "anon-id"); if (existsSync(file)) { const id = readFileSync(file, "utf8").trim(); if (id) return id;