Dashboard › sentry › Session 0BLMn3hmhuUF
0BLMn3hmhuUFYLJXUYou are a senior code reviewer. I need you to do a thorough, critical review of PR #608 on the BYK/loreai repository. The PR is titled "test(ci): quiet test harness noise + pretest hook for bundle".
The workspace is at /home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf.
git diff origin/main..HEAD in the workspacegh pr view 608 --json bodygh issue view 606 --json bodypretest fails (e.g. esbuild error)? Does the CI step still proceed?withLocalModel wrapper: Is the updated comment accurate? Does the code match what the comment says? Is the issue reference (#606) correct?[lore] active: banner gate: Is NODE_ENV === "test" reliably set in vitest? What about edge cases where the banner might be needed?pretest hook: Does pnpm pretest actually run before pnpm test? What about when running pnpm test <specific-file>? Does pretest still run?packages/pi/test/**/*.test.ts truly dead? Could removing it break anything?pretest placement correct (before build, after test)?I'll start by gathering all the information needed for this review in parallel.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 59bd830..98efd82 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -75,8 +75,9 @@ jobs:
# Build all packages so tests can resolve workspace dependencies
- run: pnpm run build
- # Bundle @loreai/gateway for tests (build.ts only creates dev shims)
- - run: pnpm --filter @loreai/gateway run bundle
+ # Note: the @loreai/gateway bundle is built by the root `pretest` script
+ # that runs before `pnpm test` (see package.json). No explicit bundle
+ # step needed here.
# Restore the vendored embedding model so tests use a local model
# instead of downloading from HuggingFace Hub (avoids transient 429s). ...
{"body":"## Summary\n\nReduces the noise CI and local dev see when running `pnpm test`. Five sources of noise addressed, each with a one-line change in most cases. Net effect: clean test output, faster runs, and a robust test harness that doesn't depend on CI ordering to keep the bundle fresh.\n\n## What changed\n\n### Noise eliminated\n\n| Source | Before | After |\n|---|---|---|\n| `ExperimentalWarning: SQLite is an experimental feature` + `(Use \\`node --trace-warnings ...\\`)` on every test worker | ~85 lines per run | 0 (`NODE_NO_WARNINGS=1` in CI test env) |\n| `[lore] active: <cwd>` banner on every in-process gateway test | 1 per test (~12 lines) | 0 (gated behind `NODE_ENV !== \"test\"` in `packages/opencode/src/index.ts`) |\n| `gateway-smoke.test.ts` failures on clean checkout (no `dist/`) | 2 failures | 0 (`pretest` hook rebuilds the bundle) |\n| `bundle-exports.test.ts` skipped when bundle missing | 1 file skipped | 0 (`pretest` ensures bundle exists) |\n\n### Other ...
{"body":"## Summary\n\n`packages/core/test/embedding.test.ts` has 6 LocalProvider tests that silently skip via a `withLocalModel` wrapper whenever `LocalProviderUnavailableError` is thrown. The wrapper is a band-aid for a **pre-existing worker init failure** that the test never actually exercises. If the wrapper is removed, all 6 tests fail loudly — surfacing a real Node.js ESM bug in the embedding worker source.\n\nThis was discovered while cleaning up the test harness (see #TBD). Scope was kept tight to test noise; the underlying bug is filed here as a follow-up.\n\n## Root cause\n\n`packages/core/src/embedding-worker.ts:31` does an extensionless relative import:\n\n```ts\n} from \"./embedding-worker-types\";\n```\n\nWhen the worker thread is spawned from source (the dev/vitest path — see `embedding.ts:331`), Node.js ESM resolves the worker file fine, but the worker's own internal import of `./embedding-worker-types` (no extension) fails:\n\n```\nError [ERR_MODULE_NOT_FOUND]: Cannot ...
Now let me examine the specific files in detail to verify claims and check for edge cases.
name: CI
on:
push:
branches: [main, 'release/**']
pull_request:
branches: [main]
# packages:write is needed for publish-nightly to push to GHCR
permissions:
contents: read
packages: write
env:
# Commit timestamp used for deterministic nightly version strings.
# Defined at workflow level so all jobs agree on the same value.
COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }}
jobs:
# ---------------------------------------------------------------------------
# Change detection: skip heavy CI for docs-only changes
# ---------------------------------------------------------------------------
changes:
runs-on: ubuntu-latest
permissions:
pull-requests: read
outputs:
code: ${{ steps.force.outputs.code || steps.filter.outputs.code }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v4
id: filter
with:
filters: |
code:
- 'packages/**'
...
{
"name": "lore-monorepo",
"private": true,
"type": "module",
"license": "FSL-1.1-Apache-2.0",
"description": "Monorepo root for Lore — three-tier memory architecture",
"main": "./packages/opencode/src/index.ts",
"exports": {
".": "./packages/opencode/src/index.ts"
},
"packageManager": "pnpm@10.28.0",
"pnpm": {
"onlyBuiltDependencies": [
"esbuild",
"sharp"
]
},
"scripts": {
"typecheck": "pnpm -r run typecheck",
"test": "vitest run",
"pretest": "pnpm --filter @loreai/gateway run bundle",
"build": "pnpm -r run build",
"site:dev": "pnpm --filter '@loreai/website' dev",
"site:build": "pnpm --filter '@loreai/website' build",
"site:preview": "pnpm --filter '@loreai/website' preview",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"evals": "vitest run --config vitest.evals.config.ts",
"postinstall": "pnpm --filter @loreai/gateway run build"
},
...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/core/test/embedding.test.ts</path>
<type>file</type>
<content>
475: .run(pid, now, now);
476:
477: const results = vectorSearchEntities(new Float32Array([1, 0, 0]), 1);
478: expect(results.length).toBe(1);
479: expect(results[0].id).toBe("ent-x");
480: });
481: });
482:
483: let loggedModelSkip = false;
484:
485: /**
486: * Run a model-dependent test body, tolerating an unavailable local model.
487: *
488: * In CI the model is vendored and `LORE_LOCAL_MODEL_PATH` points at it, so the
489: * body runs normally. When the body throws `LocalProviderUnavailableError` we
490: * SKIP rather than hard-fail, because the underlying worker init has a
491: * known pre-existing test-infra limitation: the source worker at
492: * `packages/core/src/embedding-worker.ts` does extensionless relative imports
493: * (e.g. `./embedding-worker-types`) that Node.js ESM ...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/opencode/src/index.ts</path>
<type>file</type>
<content>
240: // OpenCode's plugin SDK types don't expose `.id` on the provider
241: // object, but it IS present at runtime. Cast around incomplete typedef.
242: const providerID = (
243: input.provider as Record<string, unknown> | undefined
244: )?.id as string | undefined;
245: if (providerID) {
246: output.headers["x-lore-provider"] = providerID;
247: }
248: },
249: };
250:
251: // Startup banner — visible in stderr so silent failures are obvious.
252: // Suppressed in test env to keep vitest output clean.
253: if (!processInitDone) {
254: const projectPath = discoverWorkspaceRoot(ctx.worktree || ctx.directory);
255: if (process.env.NODE_ENV !== "test") {
256: process.stderr.write(`[lore] active: ...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/vitest.config.ts</path>
<type>file</type>
<content>
1: import { defineConfig } from "vitest/config";
2: import path from "node:path";
3:
4: export default defineConfig({
5: test: {
6: // Run all packages' tests
7: include: [
8: "packages/core/test/**/*.test.ts",
9: "packages/gateway/test/**/*.test.ts",
10: "packages/opencode/test/**/*.test.ts",
11: ],
12: // Preload test setup for DB isolation
13: setupFiles: ["./packages/core/test/setup.ts"],
14: // Environment
15: environment: "node",
16: pool: "threads",
17: // Timeouts — generous for gateway startup and LLM operations
18: testTimeout: 300_000, // 5 min per test
19: hookTimeout: 300_000,
20: // Environment variables for test isolation
21: env: {
22: NODE_ENV: "test",
23: SENTRY_ENABLED: "0",
24: LORE_DEBUG: "0",
25: },
26: // Coverage is ...
Now let me check a few more specific things to verify claims in the PR.
ls: cannot access 'packages/pi/test/': No such file or directory
LICENSE node_modules package.json README.md script src tsconfig.build.json tsconfig.json
11: cosineSimilarity,
12: toBlob,
15: vectorSearch,
16: vectorSearchEntities,
21: embed,
26:} from "../src/embedding";
28:describe("cosineSimilarity", () => {
31: expect(cosineSimilarity(a, a)).toBeCloseTo(1.0, 5);
37: expect(cosineSimilarity(a, b)).toBeCloseTo(-1.0, 5);
43: expect(cosineSimilarity(a, b)).toBeCloseTo(0.0, 5);
49: const sim = cosineSimilarity(a, b);
57: expect(cosineSimilarity(a, b)).toBe(0);
62: expect(cosineSimilarity(a, a)).toBe(0);
67: test("Float32Array survives toBlob → fromBlob", () => {
69: const blob = toBlob(original);
79: const restored = fromBlob(toBlob(original));
85: const restored = fromBlob(toBlob(original));
92: const restored = fromBlob(toBlob(original));
113: // happens lazily on first embed() call, so isAvailable() is true.
125: // have to handle a thrown error from deep inside `embed()`. ...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/core/test/embedding.test.ts</path>
<type>file</type>
<content>
1: import {
2: afterAll,
3: afterEach,
4: describe,
5: test,
6: expect,
7: beforeEach,
8: } from "vitest";
9: import { db, ensureProject } from "../src/db";
10: import {
11: cosineSimilarity,
12: toBlob,
13: fromBlob,
14: isAvailable,
15: vectorSearch,
16: vectorSearchEntities,
17: checkConfigChange,
18: _shutdownAndDisable,
19: _saveAndClearProvider,
20: _restoreProvider,
21: embed,
22: LocalProviderUnavailableError,
23: pickRemoteFallback,
24: _resetLocalProviderProbe,
25: _markLocalProviderUnavailable,
26: } from "../src/embedding";
27:
28: describe("cosineSimilarity", () => {
29: test("identical vectors return 1.0", () => {
30: const a = new Float32Array([1, 2, 3]);
(Showing lines 1-30 of 738. Use offset=31 to continue.)
</content>
20: * @see embedding-worker-types.ts for the message protocol. 31:} from "./embedding-worker-types"; 254:// isOomError and isWasmFatalError are imported from embedding-worker-types.ts
/**
* Smoke test for the npm bundle artifacts.
*
* Verifies that:
* - Every file referenced by package.json `files` and `exports` exists
* - The CJS Node bundle uses node:sqlite (not bun:sqlite)
* - The imported module exports the expected public API
*
* Requires the bundle (`pnpm --filter @loreai/gateway run bundle`) to have
* been built. The root `pretest` script runs the bundle automatically before
* `pnpm test`, so this test runs in every environment (local + CI). The
* skipIf guard is defensive — it should never trigger in normal use, but
* ensures a missing bundle is reported as a skip rather than a confusing
* file-not-found assertion failure.
*/
import { describe, test, expect } from "vitest";
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
const packageDir = join(fileURLToPath(import.meta.url), "..", "..");
const distDir = join(packageDir, "dist");
const pkgJson = JSON.parse(
...
Let me check a few more things to complete the review.
packages/gateway/test/agents.test.ts packages/gateway/test/anthropic-caching.test.ts packages/gateway/test/api.test.ts packages/gateway/test/auth.test.ts packages/gateway/test/background-limiter.test.ts packages/gateway/test/batch-queue.test.ts packages/gateway/test/budget-throttle.test.ts packages/gateway/test/bundle-exports.test.ts packages/gateway/test/cache-analytics.test.ts packages/gateway/test/cache-warmer.test.ts packages/gateway/test/cch.test.ts packages/gateway/test/compaction.test.ts packages/gateway/test/content-passthrough.test.ts packages/gateway/test/context-markers.test.ts packages/gateway/test/cost-tracker.test.ts packages/gateway/test/eviction.test.ts packages/gateway/test/hosted-config.test.ts packages/gateway/test/llm-adapter.test.ts packages/gateway/test/max-tokens.test.ts packages/gateway/test/openai-parse.test.ts packages/gateway/test/openai-responses-stream.test.ts packages/gateway/test/openai-responses.test.ts packages/gateway/test/pipeline-tools.test.ts packag...
- # Bundle @loreai/gateway for tests (build.ts only creates dev shims)
- - run: pnpm --filter @loreai/gateway run bundle
+ # Note: the @loreai/gateway bundle is built by the root `pretest` script
+ # that runs before `pnpm test` (see package.json). No explicit bundle
+ # step needed here.
--
wait $SERVER_PID 2>/dev/null || true
- - name: Smoke-test bundle exports
- run: pnpm test packages/gateway/test/bundle-exports.test.ts
+ # Note: the bundle-exports test runs as part of the main `pnpm test`
+ # step above (discovered via vitest.config.ts). No need to re-run it.
76: - run: pnpm run build 284: run: pnpm run build
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/core/test/distillation.test.ts</path>
<type>file</type>
<content>
220: describe("truncateToolOutputsInContent — perf regression guards", () => {
221: // These guards catch catastrophic regex backtracking in the path-extraction
222: // regex inside toolStripAnnotation, NOT precise latencies. The thresholds are
223: // deliberately generous: the healthy fast path runs in <1ms (no-slash) and
224: // ~0.7s (with-slash, 64KB scan cap), while a regression that removed either
225: // mitigation scans the full input and takes ~10s+. The wide gap lets us
226: // tolerate parallel-suite / CI-runner jitter without flaking while still
227: // failing loudly on an actual O(n²) regression. A warm-up call removes
228: // first-call JIT/allocation skew from the timed measurement. ...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/core/test/markdown.test.ts</path>
<type>file</type>
<content>
125: });
126: });
127:
128: describe("formatKnowledge", () => {
129: test("output === normalize(output) — AST serializer produces already-normalized markdown", () => {
130: fc.assert(
131: fc.property(
132: fc.array(
133: fc.record({
134: category: fc.oneof(
135: fc.constant("decision"),
136: fc.constant("pattern"),
137: fc.constant("gotcha"),
138: ),
139: title: hostile.filter((s) => s.trim().length > 0),
140: content: hostile.filter((s) => s.trim().length > 0),
141: }),
142: { minLength: 1, maxLength: 5 },
143: ),
144: (entries) => {
145: const result = formatKnowledge(entries);
146: if (!result) return;
147: ...
7
Let me check one more important thing — whether the CI YAML is valid and whether the removed bundle step leaves a dangling empty run.
(no output)
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/.github/workflows/ci.yml</path>
<type>file</type>
<content>
73: - run: pnpm install --frozen-lockfile
74:
75: # Build all packages so tests can resolve workspace dependencies
76: - run: pnpm run build
77:
78: # Note: the @loreai/gateway bundle is built by the root `pretest` script
79: # that runs before `pnpm test` (see package.json). No explicit bundle
80: # step needed here.
81:
82: # Restore the vendored embedding model so tests use a local model
83: # instead of downloading from HuggingFace Hub (avoids transient 429s).
84: # Same cache key as binary-smoke-native / build-nightly-binaries.
85: - name: Restore vendor staging
86: id: vendor-cache
87: uses: actions/cache@v5
88: with:
89: path: .vendor-build
90: key: vendor-${{ hashFiles('packages/core/package.json', ...
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/.github/workflows/ci.yml</path> <type>file</type> <content> 195: 196: - name: Smoke-test npm bundle under Node.js 197: run: | 198: node packages/gateway/dist/bin.cjs --version 199: node packages/gateway/dist/bin.cjs help 200: 201: # Start gateway, hit health endpoint, shut down 202: node packages/gateway/dist/bin.cjs start -p 7990 & 203: SERVER_PID=$! 204: sleep 2 205: curl -sf http://127.0.0.1:7990/health | jq . 206: kill $SERVER_PID 207: wait $SERVER_PID 2>/dev/null || true 208: 209: # Note: the bundle-exports test runs as part of the main `pnpm test` 210: # step above (discovered via vitest.config.ts). No need to re-run it. ...
79: # that runs before `pnpm test` (see package.json). No explicit bundle 103: run: pnpm test 107: # vitest's threads pool. Doesn't suppress real test failures. 209: # Note: the bundle-exports test runs as part of the main `pnpm test` 210: # step above (discovered via vitest.config.ts). No need to re-run it.
(no output)
vitest.config.ts:22: NODE_ENV: "test",
Now let me verify the CI ordering issue — does pretest run before pnpm test even when passing args, and does the double-bundle matter?
191: - name: Build npm bundle (CJS)
<path>/home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/.github/workflows/ci.yml</path>
<type>file</type>
<content>
188: # -----------------------------------------------------------------
189: # CLI: npm bundle + smoke test (every run)
190: # -----------------------------------------------------------------
191: - name: Build npm bundle (CJS)
192: run: pnpm --filter @loreai/gateway run bundle
193: env:
194: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
195:
196: - name: Smoke-test npm bundle under Node.js
197: run: |
(Showing lines 188-197 of 920. Use offset=198 to continue.)
</content>
"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsx script/build.ts",
"bundle": "tsx script/bundle.ts",
"build:binary": "tsx script/build.ts --binary",
"build:binary:sea": "tsx script/build-binary-sea.ts",
--if-present Avoid exiting with a non-zero exit code when the
script is undefined
--loglevel <level> What level of logs to report. Any logs at or
--
matching packages with prefixed streaming output.
This is the preferred flag for long-running
processes such as watch run over many packages.
-r, --recursive Run the defined package script in every package
--
--reporter-hide-prefix Hide project name prefix from output of running
scripts. Useful when running in CI like GitHub
Actions and the output from a script may create an
--
prefixed with the originating package directory.
This allows output from different packages to be
interleaved.
--if-present Avoid exiting with a non-zero exit code when the
script is undefined
--loglevel <level> What level of logs to report. Any logs at or
--
matching packages with prefixed streaming output.
This is the preferred flag for long-running
processes such as watch run over many packages.
-r, --recursive Run the defined package script in every package
--
--reporter-hide-prefix Hide project name prefix from output of running
scripts. Useful when running in CI like GitHub
Actions and the output from a script may create an
--
prefixed with the originating package directory.
This allows output from different packages to be
interleaved.
(no output)
No .npmrc found
This is a critical finding. pnpm v7+ disables pre/post scripts by default. Let me verify the exact pnpm version and behavior.
10.28.0
undefined
packages: - "packages/*"
This is a major finding. Let me verify definitively whether pretest actually runs.
> lore-monorepo@ pretest /home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf
> pnpm --filter @loreai/gateway run bundle --dry-run
> @loreai/gateway@0.24.1 bundle /home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf/packages/gateway
> tsx script/bundle.ts --dry-run
▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
src/index.ts:43:7:
43 │ if (!import.meta.url) return false;
╵ ~~~~~~~~~~~
You need to set the output format to "esm" for "import.meta" to work correctly.
▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
../core/src/embedding.ts:328:17:
328 │ typeof import.meta.url === "string" ? import.meta.url :...
╵ ~~~~~~~~~~~
You need to set the output format to "esm" for "import.meta" to work correctly. ...
(no output)
Good — pretest does run before pnpm test on this pnpm version. The --dry-run output confirms the pretest hook fired. Now let me check one more thing — does pnpm test <specific-file> also trigger pretest?
> lore-monorepo@ pretest /home/byk/.local/share/opencode/worktree/51d1015fd1f616acf9a5ffaad9331ec6b304586b/witty-wolf > pnpm --filter @loreai/gateway run bundle
Good — pretest fires even when a specific file is passed. Now let me check the postinstall script since the PR description mentions the build has a postinstall too, and verify the double-bundle situation in CI.
"postinstall": "pnpm --filter @loreai/gateway run build"
79: # that runs before `pnpm test` (see package.json). No explicit bundle 192: run: pnpm --filter @loreai/gateway run bundle
483:let loggedModelSkip = false;
502:async function withLocalModel(body: () => Promise<void>): Promise<void> {
507: if (!loggedModelSkip) {
508: loggedModelSkip = true;
532: withLocalModel(async () => {
546: withLocalModel(async () => {
569: withLocalModel(async () => {
614: withLocalModel(async () => {
627: withLocalModel(async () => {
644: withLocalModel(async () => {
38
Now let me verify the "2287 passed" claim and check the warn message text in withLocalModel.
510: "[embedding.test] local model unavailable (offline / HF download failed) — " + 512: "vendored model dir (e.g. .vendor-build/.model-cache) to run them offline.",
194: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
238: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
340: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
509: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
16: * source map resolution. When SENTRY_AUTH_TOKEN is set, sourcemaps are
208:if (process.env.SENTRY_AUTH_TOKEN) {
236: console.log(" No SENTRY_AUTH_TOKEN — skipping sourcemap upload");
Now I have enough information. Let me also quickly check the CI ordering to understand how many times the bundle gets built.
=== CI bundle execution order === 1. pnpm install --frozen-lockfile (triggers postinstall: pnpm --filter @loreai/gateway run build) 2. pnpm run build (builds all packages) 3. [REMOVED: explicit bundle step] 4. pnpm test (triggers pretest: pnpm --filter @loreai/gateway run bundle) 5. pnpm --filter @loreai/gateway run bundle (explicit, line 192, for smoke test) So the bundle is built: - Once via postinstall (build, not bundle) - Once via pretest - Once explicitly at line 192
"build": "tsx script/build.ts",
"bundle": "tsx script/bundle.ts",
"build:binary": "tsx script/build.ts --binary",
"build:binary:sea": "tsx script/build-binary-sea.ts",
"start": "tsx src/index.ts"
},
Now I have a complete picture. Let me also verify one more detail — build vs bundle are different scripts.
/**
* Build @loreai/gateway.
*
* Two build modes:
*
* 1. `bun run script/build.ts` (default)
* Produces dist/index.js — publishable ESM bundle for npm.
* @loreai/core is external (workspace dep, installed alongside).
*
* 2. `bun run script/build.ts --binary`
* Delegates to `script/build-binary-sea.ts` which produces a
* standalone Node SEA binary via fossilize. The legacy Bun
* `--compile` pipeline was removed in #551 in favor of Node SEA
* because Bun's WASM engine has unfixed bugs that cause ONNX
* embedding OOM on all platforms (oven-sh/bun#18145, #25677, #31158).
*/
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { parseArgs } from "node:util";
const here = dirname(fileURLToPath(import.meta.url));
const packageDir = dirname(here);
const distDir = join(packageDir, "dist");
// ...
/** * Bundle @loreai/gateway into a self-contained CJS package for npm/npx. * * Produces: * dist/index.cjs — single CJS bundle (gateway + core + all JS deps) * dist/bin.cjs — thin CLI wrapper with Node.js version check * * Everything is bundled except: * - node:* built-ins (resolved at runtime) * * Source code is pure Node.js — no `Bun.*` polyfill layer is needed. * (xxHash64 lives in src/xxhash.ts as a standalone module since there is * no Node.js equivalent of `Bun.hash.xxHash64`.) * * Debug IDs are injected into the JS + sourcemap after bundling for Sentry * source map resolution. When SENTRY_AUTH_TOKEN is set, sourcemaps are * uploaded to Sentry and then deleted (they shouldn't ship to users). ...
Now I have the complete picture. Let me write up the review.
test(ci): quiet test harness noise + pretest hook for bundlewithLocalModel console.warn message is stale and contradicts the updated docstringFile: packages/core/test/embedding.test.ts:510-512
The docstring was updated to explain the real root cause (extensionless ESM imports in the worker), but the console.warn message still says:
"[embedding.test] local model unavailable (offline / HF download failed) — "
"skipping model-dependent assertions. Set LORE_LOCAL_MODEL_PATH to a "
"vendored model dir (e.g. .vendor-build/.model-cache) to run them offline."
This message is now actively misleading. It tells a developer "set LORE_LOCAL_MODEL_PATH" as if that would fix the skip, but the docstring above correctly explains the skip is caused by a Node.js ESM resolution bug that has nothing to do with the model path. A developer who reads this message and follows its advice will waste time. The docstring says one thing; the runtime message says the opposite.
Severity: Medium-high. Not a CI-breaking bug, but a trap for the next person who sees the skip. Should be updated to match the docstring — mention the ESM import bug and point at #606.
pretest hook builds the bundle without SENTRY_AUTH_TOKENFile: package.json:20, .github/workflows/ci.yml:103
The pretest hook runs pnpm --filter @loreai/gateway run bundle. In CI, this runs as part of pnpm test (line 103), which does NOT have SENTRY_AUTH_TOKEN in its env: block. The later explicit bundle step (line 192) DOES have it. The bundle script (bundle.ts:208,236) skips sourcemap upload when the token is absent, so this isn't a failure, but it means:
pretest (no sourcemaps uploaded) and once at line 192 (with sourcemaps uploaded). This is redundant work (~4s wasted).