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
37 changes: 36 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ jobs:
with:
persist-credentials: false

# The required check. .nvmrc is the one place the project's Node
# version lives; Railway reads package.json engines (kept in step by
# test/toolchain.test.ts) and nvm reads .nvmrc locally.
- uses: actions/setup-node@v7
with:
node-version: 22
node-version-file: .nvmrc
cache: npm

# Fresh clone, no secrets. Tests use PGlite and in-process fakes
Expand All @@ -44,3 +47,35 @@ jobs:

- name: Build
run: npm run build

# Early warning, never blocking: the newest LTS and the newest Current
# release. When the next Node line becomes LTS, the lts/* job tests it
# before anyone moves .nvmrc and engines.
next-node:
name: Next Node (${{ matrix.node }})
runs-on: ubuntu-24.04
timeout-minutes: 10
continue-on-error: true
strategy:
fail-fast: false
matrix:
node: ['lts/*', 'latest']
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node }}
check-latest: true
cache: npm

- name: Install
run: npm ci

- name: Typecheck
run: npm run typecheck

- name: Test
run: npm test
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Refuse to install on a Node outside package.json "engines" instead of
# failing later in a confusing way. .nvmrc names the version to use.
engine-strict=true
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ Later, the coach runs all of it by texting the number in plain English.

## Prerequisites

- Node.js ≥ 20.11 (see `engines` in `package.json`). That's the whole list.
- Node.js 24 (the current LTS). `.nvmrc` names it, so `nvm use` (or a shell
that switches on `.nvmrc`) picks it up; `npm ci` refuses an older Node
(`engine-strict` in `.npmrc`). That's the whole list.
- No Postgres, no Docker, no database to install — tests run against
[PGlite](https://pglite.dev) (Postgres compiled to WASM, in-memory).
- No accounts to create and no secrets required to run locally. Payments
Expand Down
39 changes: 38 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ running database, Square, Twilio, SendGrid, or a model provider.

## Stack (decided once, in M1, not reopened)

- **Language:** TypeScript 5, Node.js ≥ 20.11, ESM (`"type": "module"`).
- **Language:** TypeScript 5, Node.js ≥ 20.11, ESM (`"type": "module"`). *(Now TypeScript 6 and Node 24; see M11.)*
- **Web:** Express 4. Server-rendered HTML via hand-written template
functions (tagged-template `html` helper with escaping) — **no templating
engine dependency, no SPA framework.**
Expand Down Expand Up @@ -1140,3 +1140,40 @@ Notes:
- The eval set is synthetic. Its pass rate means little until the launch
coach's own descriptions are in it.

---

## M11: Current toolchain, one Node version everywhere
Status: [x] done
Goal: Run on the current Node LTS and current dependencies, with the Node
version named once and every environment reading it.
Acceptance:
- [x] `.nvmrc` is `24`; `package.json` `engines.node` is `>=24`;
`test/toolchain.test.ts` fails if they name different lines, if the
line is odd (non-LTS), or if CI stops reading `.nvmrc`
- [x] Production's Node is known, not assumed: Node 22.23.2 in all three
Railway environments (read from the running containers), pinned by a
`RAILPACK_NODE_VERSION=22` variable that Railpack reads before
`engines`. It stays on 22 until that variable changes; M12 makes
`.railway/railway.ts` set it from `.nvmrc`
- [x] CI's required `CI` check runs on `.nvmrc`; a non-blocking
`Next Node` job runs `lts/*` and `latest`, so the next LTS is tested
before anyone moves the pin
- [x] `npm ci` on an older Node fails fast (`engine-strict`)
- [x] Express 5, PGlite 0.5, TypeScript 6.0, ESLint 10, `@types/node` 24,
and current minors, with no source changes beyond the boot log;
compiler target ES2024
- [x] All five quality-bar commands exit 0 on Node 24

Notes:
- TypeScript 7 is out but `typescript-eslint` supports below 6.1, so 6.0.3
is the newest usable. Revisit when `typescript-eslint` widens its range.
- npm 12 (with Node 24) blocks install scripts unless allowed;
`package.json` `allowScripts` permits esbuild's and fsevents', which npm
10 ran anyway. Older npm ignores the field.
- Express 5 sends a rejected async handler to the error handler. Under
Express 4 such a request never got a response.
- The server logs its Node version at boot, so `railway logs` shows what a
deploy actually runs.
- To move to the next LTS: change `.nvmrc` and `engines` together (the
toolchain test enforces it), after the `Next Node (lts/*)` job is green.

Loading
Loading