From 67220746a8573deec9248c0b54e0e51260590cfb Mon Sep 17 00:00:00 2001 From: Jason McCartney Date: Sun, 11 Oct 2026 20:18:47 -0700 Subject: [PATCH] init: record this run's recipe sources instead of inheriting stale ones An additive init spread the previous init block and only overwrote recipesRoot/benchmarksRoot/backendCatalogPath when the new run passed them. Installing a packaged recipe (default root) on top of a setup from a custom recipes directory left init.recipeId pointing at a recipe that the stale init.recipesRoot does not contain, so `lloom status` failed with "Unknown recipe lloom-hear" on ennspark03. Co-Authored-By: Claude Opus 5.5 --- src/init.mjs | 7 ++++--- test/hear-recipe.test.mjs | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/init.mjs b/src/init.mjs index 32defc8..b0d8a79 100644 --- a/src/init.mjs +++ b/src/init.mjs @@ -1417,9 +1417,10 @@ export function deriveUserConfig( enabledRuntimes: additive ? [...new Set([...(derived.init?.enabledRuntimes ?? []), ...runtimeIds])] : runtimeIds, keepWarmRuntime: additive ? null : keepWarm, additive, - ...(recipesRoot ? { recipesRoot } : {}), - ...(benchmarksRoot ? { benchmarksRoot } : {}), - ...(backendCatalogPath ? { backendCatalogPath } : {}) + // This run's sources replace the previous init's: recipeId is only valid in its own root. + recipesRoot: recipesRoot || undefined, + benchmarksRoot: benchmarksRoot || undefined, + backendCatalogPath: backendCatalogPath || undefined }; return preserveEnvBackedSecrets(derived, sourceTemplate); } diff --git a/test/hear-recipe.test.mjs b/test/hear-recipe.test.mjs index 7eedc47..cefa6c7 100644 --- a/test/hear-recipe.test.mjs +++ b/test/hear-recipe.test.mjs @@ -59,4 +59,18 @@ assert.match(next.backends.hear.baseUrl, /^http:\/\/127\.0\.0\.1:\d+\/v1$/); assert.deepEqual(next.aliases.hear.members, ['hear']); assert.deepEqual(next.aliases.listen.members, ['hear']); +// An additive init from the default recipes must not inherit an earlier init's +// sources, or `lloom status` resolves the new recipeId in the old recipes root. +const staleSources = { + recipesRoot: '/stale/recipes', + benchmarksRoot: '/stale/benchmarks', + backendCatalogPath: '/stale/backends.json' +}; +const restacked = await createInitPlan( + { ...config, init: { recipeId: 'spark03-cuda-media', ...staleSources } }, + { recipeId: 'lloom-hear', additive: true, modelRoot: '/tmp/lloom-models' } +); +assert.equal(restacked.config.init.recipeId, 'lloom-hear'); +for (const key of Object.keys(staleSources)) assert.equal(restacked.config.init[key], undefined, key); + console.log('hear-recipe tests passed');