Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
node-version-file: ".nvmrc"
cache: npm

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .node-version
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
22
24
2 changes: 1 addition & 1 deletion .nvmrc
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
22
24
2 changes: 1 addition & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@ questions with source citations that link back to the original PDF/document.

## Setup

1. Use Node.js 22.x. CI runs on Node 22, and `.nvmrc` / `.node-version`
1. Use Node.js 24.x. CI runs on Node 24, and `.nvmrc` / `.node-version`
pin the same runtime for local version managers.
2. Copy `.env.example` to `.env.local` and fill in Supabase and OpenAI values.
3. Confirm the Supabase target:
Expand Down
4 changes: 2 additions & 2 deletions docs/process-hardening.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ This document turns the current process review into phased, durable repo practic

## Phase 4 - Release maturity

- `npm run check:runtime` is the strict release runtime gate and is now part of `npm run verify:release`; it fails outside Node 22.x.
- CI runs `npm run check:runtime` after dependency install so branch verification cannot silently drift to Node 24+.
- `npm run check:runtime` is the strict release runtime gate and is now part of `npm run verify:release`; it fails outside Node 24.x.
- CI runs `npm run check:runtime` after dependency install so branch verification cannot silently drift to Node 25+.
- Decide whether CI should run all Playwright browser projects on protected branches, release branches, or a scheduled workflow instead of every push.
- Add explicit review ownership for clinical source governance, outdated-source handling, incident review, and decommission decisions.
- Record production-readiness outcomes in release notes whenever clinical workflow, source governance, privacy, or deployment assumptions change.
Expand Down
4 changes: 2 additions & 2 deletions docs/production-readiness-checklist.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@
This is the runbook to make the app publishable in one focused pass.

- Branch: `codex/premium-redesign` (do not touch `.env` / secrets directly).
- Runtime target: Next.js 16.2.7, Node 22.x, npm >= 10.
- Runtime target: Next.js 16.2.7, Node 24.x, npm >= 11.
- Supabase target: `sjrfecxgysukkwxsowpy` (`Clinical KB Database`).

## Immediate completion targets
Expand All@@ -21,7 +21,7 @@ This is the runbook to make the app publishable in one focused pass.
- used in CI and non-blocking on local-only secret absence.
- [x] Added strict runtime release gate:
- `npm run check:runtime`
- enforces Node 22.x before `npm run verify:release`.
- enforces Node 24.x before `npm run verify:release`.

## Remaining high-priority publish items (same day)

Expand Down
8 changes: 4 additions & 4 deletions docs/project-alignment-cleanup.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,15 +10,15 @@
## Dependency verification note

- `npm ci` and `npm audit --json` are the release gates for dependency install and security status.
- On Windows with npm 10, `npm ls --depth=0` can report bundled optional wasm/native packages as extraneous immediately after `npm ci`: `@emnapi/core`, `@emnapi/runtime`, `@emnapi/wasi-threads`, `@napi-rs/wasm-runtime`, and `@tybys/wasm-util`.
- On Windows with npm 11, `npm ls --depth=0` can report bundled optional wasm/native packages as extraneous immediately after `npm ci`: `@emnapi/core`, `@emnapi/runtime`, `@emnapi/wasi-threads`, `@napi-rs/wasm-runtime`, and `@tybys/wasm-util`.
- `npm explain` traces these packages to optional wasm/native dependency paths from `@tailwindcss/oxide-wasm32-wasi`, `@rolldown/binding-wasm32-wasi`, and `@unrs/resolver-binding-wasm32-wasi`; the lockfile contains those paths and `npm audit --json` reports zero vulnerabilities.
- Do not treat this specific `npm ls --depth=0` extraneous output as a hard release blocker unless audit fails, install fails, package versions drift from `package-lock.json`, or a future npm/package update stops reproducing the optional-dependency reporting issue.

## Runtime policy

- CI verifies the project on Node.js 22, so local development should also use Node.js 22.x.
- `.nvmrc`, `.node-version`, and `package.json` `engines` all declare the Node 22 runtime expectation.
- New cleanup or dependency work should be verified on Node 22 before release, even when local shells happen to use newer Node versions.
- CI verifies the project on Node.js 24, so local development should also use Node.js 24.x.
- `.nvmrc`, `.node-version`, and `package.json` `engines` all declare the Node 24 runtime expectation.
- New cleanup or dependency work should be verified on Node 24 before release, even when local shells happen to use newer Node versions.

## Stale branch audit

Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@
"private": true,
"packageManager": "npm@10.9.8",
"engines": {
"node": "22.x",
"npm": "10.x"
"node": "24.x",
"npm": "11.x"
},
Comment on lines 5 to 9
"scripts": {
"dev": "node scripts/dev-free-port.mjs",
Expand DownExpand Up@@ -98,7 +98,7 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4.3.0",
"@types/node": "^25.9.2",
"@types/node": "^24",
"@types/pdf-parse": "^1.1.5",
"@types/pdfkit": "^0.17.6",
"@types/react": "^19.2.17",
Expand Down
8 changes: 4 additions & 4 deletions scripts/check-node-engine.cjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,12 +3,12 @@ const npmUserAgent = process.env.npm_config_user_agent ?? "";
const npmVersion = npmUserAgent.match(/\bnpm\/(\d+\.\d+\.\d+)/)?.[1] ?? "";
const npmMajor = Number(npmVersion.split(".")[0]);

if (major !== 22) {
console.error(`This project must be installed with Node 22.x. Current runtime: ${process.versions.node}.`);
if (major !== 24) {
console.error(`This project must be installed with Node 24.x. Current runtime: ${process.versions.node}.`);
process.exit(1);
}

if (npmVersion && npmMajor !== 10) {
console.error(`This project must be installed with npm 10.x. Current npm runtime: ${npmVersion}.`);
if (npmVersion && npmMajor !== 11) {
console.error(`This project must be installed with npm 11.x. Current npm runtime: ${npmVersion}.`);
process.exit(1);
}
4 changes: 2 additions & 2 deletions scripts/check-runtime.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,11 +43,11 @@ function runtimeResult(runtimeName: string, version: string, expectedMajor: numb
};
}

export function checkNodeRuntime(version: string, expectedMajor = 22): RuntimeCheckResult {
export function checkNodeRuntime(version: string, expectedMajor = 24): RuntimeCheckResult {
return runtimeResult("Node", version, expectedMajor);
}

export function checkNpmRuntime(userAgent = process.env.npm_config_user_agent ?? "", expectedMajor = 10): RuntimeCheckResult {
export function checkNpmRuntime(userAgent = process.env.npm_config_user_agent ?? "", expectedMajor = 11): RuntimeCheckResult {
if (!userAgent) {
return {
ok: true,
Expand Down
4 changes: 2 additions & 2 deletions scripts/dev-free-port.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ import path from "node:path";
import { fileURLToPath } from "node:url";
import { appName, stableProjectPort } from "./local-server-utils.mjs";

if (Number(process.versions.node.split(".")[0]) !== 22) {
console.error(`Clinical KB local server requires Node 22.x. Current runtime: ${process.versions.node}.`);
if (Number(process.versions.node.split(".")[0]) !== 24) {
console.error(`Clinical KB local server requires Node 24.x. Current runtime: ${process.versions.node}.`);
process.exit(1);
}

Expand Down
4 changes: 2 additions & 2 deletions scripts/ensure-local-server.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,8 +7,8 @@ import path from "node:path";
import { fileURLToPath } from "node:url";
import { appName, localProjectId, projectPortEnd, stableProjectPort } from "./local-server-utils.mjs";

if (Number(process.versions.node.split(".")[0]) !== 22) {
console.error(`Clinical KB local server requires Node 22.x. Current runtime: ${process.versions.node}.`);
if (Number(process.versions.node.split(".")[0]) !== 24) {
console.error(`Clinical KB local server requires Node 24.x. Current runtime: ${process.versions.node}.`);
process.exit(1);
}

Expand Down
18 changes: 9 additions & 9 deletions tests/check-runtime.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,30 +3,30 @@ import { describe, expect, it } from "vitest";
import { checkNodeRuntime, checkNpmRuntime } from "../scripts/check-runtime";

describe("runtime release gate", () => {
it("accepts the Node 22 release target", () => {
expect(checkNodeRuntime("22.22.3")).toMatchObject({
it("accepts the Node 24 release target", () => {
expect(checkNodeRuntime("24.15.0")).toMatchObject({
ok: true,
expectedMajor: 22,
expectedMajor: 24,
});
});

it("rejects older and newer major runtimes", () => {
expect(checkNodeRuntime("21.7.0")).toMatchObject({ ok: false });
expect(checkNodeRuntime("24.15.0")).toMatchObject({ ok: false });
expect(checkNodeRuntime("23.11.0")).toMatchObject({ ok: false });
expect(checkNodeRuntime("25.0.0")).toMatchObject({ ok: false });
});

it("reports unparsable runtime versions as failures", () => {
expect(checkNodeRuntime("not-a-version")).toMatchObject({ ok: false });
});

it("accepts the npm 10 release package manager", () => {
expect(checkNpmRuntime("npm/10.9.8 node/v22.22.3 win32 x64")).toMatchObject({
it("accepts the npm 11 release package manager", () => {
expect(checkNpmRuntime("npm/11.12.1 node/v24.15.0 win32 x64")).toMatchObject({
ok: true,
expectedMajor: 10,
expectedMajor: 11,
});
});

it("rejects newer npm majors for release verification", () => {
expect(checkNpmRuntime("npm/11.17.0 node/v22.22.3 win32 x64")).toMatchObject({ ok: false });
expect(checkNpmRuntime("npm/12.0.0 node/v24.15.0 win32 x64")).toMatchObject({ ok: false });
});
});