Skip to content

v4.2.6 fix(doctor,hooks): resolve better-sqlite3 via require.resolve (follow npm hoisting)#47

Merged
kevintseng merged 1 commit into
mainfrom
fix/native-binding-hoisting-v4.2.6
May 13, 2026
Merged

v4.2.6 fix(doctor,hooks): resolve better-sqlite3 via require.resolve (follow npm hoisting)#47
kevintseng merged 1 commit into
mainfrom
fix/native-binding-hoisting-v4.2.6

Conversation

@kevintseng
Copy link
Copy Markdown
Contributor

Summary

v4.2.5 shipped a regression: every fresh npm install @pcircle/memesh saw [FAIL] Native SQLite binding from memesh doctor, even though the binding worked. The new check pre-existence-tested <packageRoot>/node_modules/better-sqlite3 literally, but npm hoists deps to the consumer's top-level node_modules/.

Found by clean-room verifying v4.2.5:

$ mkdir /tmp/verify && cd /tmp/verify
$ npm install @pcircle/memesh@4.2.5
$ ./node_modules/.bin/memesh doctor
Overall: FAIL
[FAIL] Native SQLite binding   ← false negative

Both surfaces (src/core/doctor.ts and scripts/hooks/_shared.js) now resolve via require.resolve('better-sqlite3', { paths: [pkgRoot] }), which uses Node's normal resolution algorithm and finds hoisted packages. The hook's npm rebuild self-heal also retargets cwd to the project that owns the hoisted tree.

Docs synced

  • CHANGELOG.md updated for the change
  • docs/ARCHITECTURE.md version header bumped (module list unchanged)
  • docs/api/API_REFERENCE.md version header bumped (surface unchanged)
  • README.md no user-facing changes (locales untouched)
  • CLAUDE.md updated (gitignored — version header bumped locally)
  • Version files bumped consistently: package.json + plugin.json + marketplace.json + CHANGELOG header + ARCHITECTURE + API_REFERENCE + CLAUDE.md (4.2.5 -> 4.2.6)
  • dist/skills-manifest.json regenerated via npm run build
  • memesh doctor reports Overall: PASS_WITH_CONCERNS, Native SQLite binding PASS

Test plan

  • Clean-room verify: mktemp -d && npm install @pcircle/memesh@<staging> confirms native-binding check PASSes on hoisted install
  • npm test --run: 1036/1038 (same 2 pre-existing failures from main — tests/transports/http.test.ts recall-empty, tests/tools.test.ts auto-archive)
  • npm run lint: clean
  • npx tsc --noEmit: clean
  • npm run build: smoke 6/6
  • Updated doctor test (reports FAIL with npm install hint when better-sqlite3 is not resolvable) exercises MODULE_NOT_FOUND probe response

…ow npm hoisting (v4.2.6)

The v4.2.5 native-binding probe regressed every fresh `npm install
@pcircle/memesh` install: it pre-checked
`<packageRoot>/node_modules/better-sqlite3` literally, but npm hoists
dependencies to the consumer's top-level node_modules. So when memesh
is installed as a dependency the directory at the literal path doesn't
exist even though `require('better-sqlite3')` works correctly via
Node's normal resolution.

Found this by verifying the v4.2.5 release with a clean-room install:

    $ mkdir /tmp/verify && cd /tmp/verify
    $ npm install @pcircle/memesh@4.2.5
    $ ./node_modules/.bin/memesh doctor
    Overall: FAIL
    [FAIL] Native SQLite binding   ← false negative on a working install

The fix in both surfaces (doctor.ts and _shared.js) is to drop the
existence-precheck and call `require.resolve('better-sqlite3',
{ paths: [pkgRoot] })`. Node's resolver walks the same path the
runtime uses (current dir → parent → ancestor's node_modules) and
returns the resolved module path, which we walk back to the package
root. A MODULE_NOT_FOUND error from the probe surfaces as a clean
"run `npm install`" hint; a `bindings file` error still surfaces as
the rebuild hint from v4.2.5.

The hook self-heal also retargets `npm rebuild`'s cwd to the project
that owns the hoisted node_modules tree (walking up until a
non-node_modules package.json appears). Running rebuild from memesh's
own pkgRoot would no-op when the binary is hoisted elsewhere.

Validation:
- Local clean-room install: smoke test confirms 4.2.6 doctor PASSes
  on a hoisted install
- npm test --run: 1036/1038 (same 2 pre-existing failures as v4.2.5)
- memesh doctor: Overall: PASS_WITH_CONCERNS, native-binding PASS
- npm run lint: clean

Version bumped 4.2.5 -> 4.2.6 across all 7 anchor files. The CodeQL
config and TOCTOU fix from v4.2.5 carry forward unchanged.
@github-actions
Copy link
Copy Markdown

Multi-Model Synthesis

Both Claude and Codex reviews above are independent. The most
valuable signals are the issues only ONE model raised
— those
are the blind spots single-model review misses.

Reviewer responsibility: read both, surface non-overlapping
findings, decide which need fixing before merge.

@kevintseng kevintseng merged commit fa3aa7b into main May 13, 2026
15 checks passed
@kevintseng kevintseng deleted the fix/native-binding-hoisting-v4.2.6 branch May 13, 2026 05:55
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