Fail loud on missing local-embedding peer dep + ship -local Docker image (#88)#131
Merged
Conversation
…emantics Issue #88 local-embeddings closeout, Unit 1. - Add a shared resolveLocalEmbeddingDep() / assertLocalEmbeddingDepForProvider() helper in config.ts and a single LOCAL_EMBEDDING_DEP_MESSAGE. - serve startup now eagerly resolves @xenova/transformers when embedding.provider is "local" and exits non-zero at boot with an actionable message (install the peer OR use ghcr.io/copilotkit/pathfinder:latest-local), instead of booting fine and throwing lazily at first embed. - validate: route the optional-dep check to a new result.warnings[] field so the command exits 0 when only warnings exist (previously it pushed to errors[] and exited 1 while printing "no hard errors"). The Optional Dependencies display block is preserved; the schema early-return is untouched. - Tests: startup guard (local+absent fail, local+present ok, non-local+absent ok) and validate exit-0-with-warning; existing validate tests updated for warnings[]. Includes the authoritative design spec.
Issue #88 local-embeddings closeout, Unit 2. - Dockerfile prod stage: add ARG INCLUDE_LOCAL_EMBEDDINGS=false; after npm ci --omit=dev, conditionally npm install @xenova/transformers only when the arg is true. Default build stays slim. - publish-docker.yml: build two variants in the same run from the same Dockerfile with disjoint tags — default (slim) -> :latest, :<ref>; local (arg=true) -> :latest-local, :<ref>-local. Both multi-arch, shared gha cache, one Slack notify summarizing both. Triggers and tag-resolution from #130 preserved. Verified locally: --build-arg INCLUDE_LOCAL_EMBEDDINGS=true -> require.resolve PRESENT; default build -> ABSENT.
Issue #88 local-embeddings closeout, Unit 3. - docs/deploy: note :latest-local ships @xenova/transformers preinstalled and that the default image now fails loudly at startup for provider: local. - docs/config: cross-reference the -local image vs npm install for the local embedding provider. - README: one-line pointer to the -local image for local embeddings in Docker.
jpr5
added a commit
that referenced
this pull request
Jun 26, 2026
Removes `docs/superpowers/specs/2026-06-25-local-embeddings-88-closeout-design.md`, which was erroneously committed via #131. Design specs belong on Notion, never in the repository.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the local-embeddings half of #88. (The schema half shipped in v1.16.0.)
@xenova/transformersis an optional peer dep absent from the published Docker image, soprovider: localfailed — and failed silently in the common path. This PR makes it fail loudly and ships a supported Docker path. Three independent units; the authoritative design spec is included in the branch (docs/superpowers/specs/2026-06-25-local-embeddings-88-closeout-design.md).Unit 1 — fail loud + fix validate semantics
servenow eagerly resolves@xenova/transformersat boot whenembedding.provider === "local". If absent, the process exits non-zero immediately with an actionable message (install the peer or useghcr.io/copilotkit/pathfinder:latest-local). Previously it booted fine and threw lazily at first embed.result.warnings[]field instead ofresult.errors[], sovalidateexits 0 when only warnings exist (it's a static linter; the startup guard is the real enforcement). The "Optional Dependencies" display block and the schema early-return are unchanged.resolveLocalEmbeddingDep()/assertLocalEmbeddingDepForProvider()helper (with oneLOCAL_EMBEDDING_DEP_MESSAGE) backs both the startup guard and validate.Unit 2 —
-localDocker image variantARG INCLUDE_LOCAL_EMBEDDINGS=falseto the prod stage; afternpm ci --omit=dev, conditionallynpm install @xenova/transformersonly when the arg istrue. Default build stays slim.:latest,:<ref>; local (INCLUDE_LOCAL_EMBEDDINGS=true) →:latest-local,:<ref>-local. Both multi-arch, sharedtype=ghacache, one Slack notify summarizing both. Theworkflow_call/workflow_dispatch/push:tagstriggers and tag-resolution step from Fix broken release→Docker publish pipeline (stale :latest at v1.15.0) #130 are preserved.Unit 3 — docs
docs/deploy: notes:latest-localships@xenova/transformerspreinstalled and that the default image now fails loudly at startup forprovider: local.docs/config: cross-references the-localimage vsnpm installfor the local provider.README.md: one-line pointer to the-localimage.Local RED→GREEN proof (real surfaces)
All runs used a schema-valid
provider: localconfig with@xenova/transformersgenuinely ABSENT fromnode_modules.Unit 1 — startup guard (
serve)serveboots past the embedding config with no mention of@xenova/transformers(grep count0) and only dies later on the DB connection (ECONNREFUSED) — i.e. with a reachable DB it would boot a healthy-looking server that explodes at first embed.serveexits 1 at boot:Unit 1 — validate exit code
validateon the schema-valid local config printsResult: 1 optional dependency warning(s), no hard errors.yet exits 1 (the self-contradiction).Unit 2 — Docker variants (built locally before CI)
docker buildx build --build-arg INCLUDE_LOCAL_EMBEDDINGS=true --target prod -t pf:local .→docker run --rm pf:local node -e "require.resolve('@xenova/transformers')…"→ PRESENTdocker buildx build --target prod -t pf:slim .→ same probe → ABSENTTest suite
Full
npx vitest run(excluding**/.claude/**): 171 files / 3192 tests passed, 0 failures. Prettier--checkclean,tscbuild clean,tsc -p tsconfig.scripts.jsonclean, version-sync in sync. Noas any.A follow-up release ships the
-localimage and the startup guard (the matrix docker build only runs on release/dispatch, not on this PR — so PR CI here is Static Quality only). Do not merge as a release commit.🤖 Generated with Claude Code