Skip to content

fix(setup): bare root npm install produces a buildable tree on Node 24#240

Merged
hoangsonww merged 7 commits into
masterfrom
fix/root-install-installs-client
Jul 18, 2026
Merged

fix(setup): bare root npm install produces a buildable tree on Node 24#240
hoangsonww merged 7 commits into
masterfrom
fix/root-install-installs-client

Conversation

@hoangsonww

Copy link
Copy Markdown
Owner

Summary

A fresh clone + npm run build failed to resolve @fontsource/inter/latin-400.css. This PR makes a bare npm install at the repo root produce a fully buildable/runnable tree, and fixes the Node 24 / Windows gaps that surfaced along the way.

Changes

1. Client deps install on a root npm install

The client's fonts (@fontsource/*) and build toolchain live in client/package.json, which a plain root npm install never installed. A root postinstall hook (scripts/postinstall.js) now installs them.

  • Guarded no-op when client/ is absent, so the multi-stage Dockerfiles (root server-deps stage, the MCP image's file:.. link) and the published tarball still install cleanly.
  • Uses shell: true so npm's Windows .cmd shim resolves (Node ≥18.20 / CVE-2024-27980).
  • Skipped under --ignore-scripts (documented fallback: cd client && npm install).

2. better-sqlite3 ^11^12

11.x ships no prebuilt binary for Node 24, so on Node 24 it falls back to a source build requiring the MSVC C++ toolchain and fails (the optional dep is then silently skipped). 12.x has Node 24 prebuilds and installs with no compiler. engines.node bumped to >=20 (better-sqlite3 12's floor; the node:sqlite fallback already needs 22+). The app still runs on the node:sqlite fallback when the native driver is absent.

3. Two Windows-only path-semantics test failures

Both are green on macOS/Linux and behave identically there after the fix — they only fail when the suite runs on Windows:

  • scripts/import-history.js classifyJsonl split on path.sep (\ on Windows), turning a POSIX "/a/b/subagents/x.jsonl" path into one segment that never equals "subagents" → subagents misclassified as sessions. Now splits on both separators.
  • server/routes/hooks.js livenessReap used the platform-sensitive path.isAbsolute; the tests mock the probe to run the reaper on Windows, where "D:\..." reads as absolute and wrongly reaps a forwarded remote session. Now uses path.posix.isAbsolute, matching the documented intent.

Docs

Synced the Node floor (18 → 20) and the client-install note across README (+VN/CN/KO), INSTALL, SETUP, ARCHITECTURE, server/client READMEs, docs/*, the landing page, and the wiki (badges + service-worker cache bump).

Verification

  • npm run test:server665 pass / 0 fail / 1 skipped (666 total)
  • Client suite (via pre-commit hook) — 261 passed
  • npm run build — succeeds
  • Verified end-to-end: wiped client/node_modules, ran only npm install from root, then npm run build → green
  • better-sqlite3 12.11.1 loads via prebuild on Node 24 with no compiler

Note: desktop/package.json still pins better-sqlite3@^11.7.0 (Electron-ABI rebuild) — intentionally out of scope here; tracked for the desktop/Windows-app follow-up.

🤖 Generated with Claude Code

…Node 24

Three related install/setup fixes so `npm install` at the repo root "just
works" on a fresh clone — the trigger was `npm run build` failing to resolve
"@fontsource/inter/latin-400.css".

1. Client deps on root install. The client's fonts (@fontsource/*) and build
   toolchain live in client/package.json, which a plain root `npm install`
   never installed. Add a root `postinstall` hook (scripts/postinstall.js) that
   installs them. It is a guarded no-op when client/ is absent, so the
   multi-stage Dockerfiles (root server-deps stage, mcp `file:..` link) and the
   published tarball still install cleanly; it uses shell:true so npm's Windows
   .cmd shim resolves. Skipped under --ignore-scripts.

2. better-sqlite3 ^11 -> ^12. 11.x ships no prebuilt binary for Node 24, so on
   Node 24 it falls back to a source build that needs the MSVC C++ toolchain
   and fails; the optional dep is then skipped. 12.x has Node 24 prebuilds and
   installs with no compiler. Bump engines to node >=20 (better-sqlite3 12's
   floor; the node:sqlite fallback already needs 22+). The app still runs on
   the node:sqlite fallback when the native driver is absent.

3. Two Windows-only path-semantics test failures (green on macOS/Linux, so
   never seen there; identical behavior on POSIX after the fix):
   - scripts/import-history.js classifyJsonl split on path.sep ("\\" on
     Windows) turned a POSIX "/a/b/subagents/x.jsonl" path into one segment
     that never equals "subagents", misclassifying subagents as sessions. Split
     on both separators instead.
   - server/routes/hooks.js livenessReap used the platform-sensitive
     path.isAbsolute; the tests mock the probe to run this reaper on Windows,
     where "D:\..." reads as absolute and wrongly reaps a forwarded remote
     session. Use path.posix.isAbsolute to match the documented intent.

Docs: sync the Node floor (18 -> 20) and the client-install note across
README (+VN/CN/KO), INSTALL, SETUP, ARCHITECTURE, server/client READMEs,
docs/*, the landing page, and the wiki (badges + cache bump).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 18, 2026 05:14
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested labels Jul 18, 2026
hoangsonww and others added 6 commits July 17, 2026 22:52
The root `postinstall` hook added in this PR (`node scripts/postinstall.js`)
fires during `npm ci` in the `server-deps` stage, but that stage copied only
the root manifest. npm aborted with `Cannot find module
'/app/scripts/postinstall.js'` (MODULE_NOT_FOUND) before installing anything,
failing the "🐳 Docker → GHCR" job.

Copy `scripts/postinstall.js` before `npm ci` so npm can load it; the script
already self-skips when `client/` is absent (as it is in this stage). Copy just
the one file, not the whole `scripts/` dir, to keep the deps-cache layer from
busting on unrelated script edits. Not using `--ignore-scripts`: that would also
skip better-sqlite3's prebuild fetch and silently drop the native SQLite driver.

Verified: full `docker build` succeeds (BUILD_EXIT=0); postinstall runs and
logs the no-op skip; better-sqlite3's prebuild-install still runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ping it to Waiting

Claude Code fires SessionStart with source ∈ startup|resume|clear|compact.
The handler stamped `awaiting_input_since = session_start` on every source, but
`compact` fires MID-TURN when auto-compaction kicks in while Claude is actively
working — the session is not sitting at a prompt. So a genuinely-active session
was mislabeled Waiting the moment a compaction (or the dashboard first seeing
that event on startup) landed.

Guard the awaiting-stamp and the waiting→working promotion behind
`source !== 'compact'`. For a compact SessionStart the pre-compaction state is
now preserved verbatim:
- mid-turn (working, no flag) → stays Active
- idle at the prompt (flag from prior Stop) → stays Waiting, reason not clobbered

startup/resume/clear are unchanged — they still land the session in Waiting.

Adds two regression tests (working-through-compact stays Active; idle-through-
compact preserves the Waiting flag and its reason). Syncs the session lifecycle
state machines and the awaiting_* column docs. All 668 server tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Propagates the "mid-turn compaction keeps the session Active (not Waiting)"
behavior from the hooks.js fix across every doc that models it:

- Session state machine (mermaid) — add `active --> active: SessionStart compact
  (state preserved)` and scope the init transition to startup/resume/clear, in
  README.md + VN/CN/KO, wiki/index.html. (server/README.md + docs/DATABASE.md
  were done in the fix commit.)
- Hook Events table — the SessionStart row in README.md + VN/CN/KO and
  wiki/index.html now notes the `compact` exception. The wiki row is i18n-keyed,
  so the zh/vi/ko entries in wiki/i18n-content.js are updated in lock-step (key +
  value); jsdom verify confirms all three still resolve.
- docs/HOOKS.md SessionStart section: document the four `source` values and the
  compact carve-out for the awaiting flag.
- ARCHITECTURE.md routes/hooks.js row: awaiting overlay is stamped on
  startup/resume/clear only.

Wiki caches bumped (CACHE_NAME wiki-v42→v43, i18n-content.js?v=32→33). Verified:
doc-coverage(compact) HITs every mapped doc; no stray Node 18 / better-sqlite3 11
remain in the maintained surface (MCP stays 18.18 by design); header audit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Minor bump for this change-set: the Node 18→20 engine drop and better-sqlite3
11→12 upgrade are compatibility-affecting for downstream/local installs, plus
the Docker-build and compact→Active hook fixes. Landing this version on master
(via this PR) is what cuts the v1.4.0 GitHub Release and rebuilds the macOS DMGs
and Windows EXEs — the CI release job publishes vX.Y.Z from the root
package.json version when no release exists for it yet.

Bumps root package.json + package-lock.json and desktop/package.json +
desktop/package-lock.json (the desktop app version labels the DMG/EXE artifacts).
client, mcp, and vscode-extension version independently and are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The test file merged from master (#238) shipped without the mandated
`@author` header line. Add it so the repo-wide header audit
(.claude/skills/file-headers/scripts/check-headers.sh) exits 0 again.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hoangsonww
hoangsonww merged commit a2541db into master Jul 18, 2026
19 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed question Further information is requested

Projects

Development

Successfully merging this pull request may close these issues.

2 participants