v4.24 — Dependency Convergence & Upgrade
Seven packages, one version matrix: Ruby, Rails, Node, and the whole Vue toolchain land on newest-stable, and the repo's worst laggard —
ionic_frontend— closes the gap on every axis a real cost-benefit case supports.
Summary
Before this milestone, the Enkidu monorepo's seven packages (rails_api, design_system, admin_dashboard, ionic_frontend, agent_runner, docs_site, guide_site) had drifted onto different majors and minors of the same core dependencies. Node was split 20/22 across CI and Docker. ionic_frontend — the app carrying production mobile builds — was stuck on Vue 3.3, vue-router 4.2, Vite 7.3, and vue-tsc 2.1 while admin_dashboard had already moved to Vue 3.5, vue-router 5, Vite 8, and vue-tsc 3. agent_runner carried floating dependency ranges (vitest: latest, vite: >=8.0.16) that were themselves a source of drift. The longer this went on, the more painful and risky the eventual convergence would get.
This milestone closed that gap deliberately, one phase at a time, behind a single committed version matrix. Ruby moved to 4.0.6, Node to 24 (Active LTS), and every package that could take a breaking major did — but only where an explicit cost-benefit case supported it. vue-router 4→5 and TypeScript 5→6 both got a POSITIVE verdict and shipped across every package that needed them, including ionic_frontend. Vite 7→8 got a NEGATIVE verdict specifically for ionic_frontend — its vite.config.ts hits three of Vite 8's named breaking changes plus a fragile Capacitor/PWA-elements workaround — so ionic_frontend deliberately stayed on Vite 7.3.5 while converging everywhere else. That's not a gap; it's the milestone's one real decision gate working as designed.
All five phases shipped in roughly 24 hours (Phase 1 kicked off 2026-07-29, the rest landed 2026-07-30), with zero rollbacks and no cross-phase rework. Every package's build and test suite is green on the new pinned toolchain, and the repo now has exactly one Node version (with ten documented, upstream-forced exceptions for Firebase-deploy steps) instead of a silent 20/22 split.
Goal
Bring every package in the Enkidu monorepo to newest-stable Ruby / Rails / Node / Vue toolchains and converge them onto one shared version matrix, so the repo stops carrying multiple simultaneous versions of the same core dependency. Every package's build + test suite stays green; CI and Dockerfiles read one Node version; the target matrix is a committed source of truth.
Scope — What Shipped
- A committed, sourced version matrix (
.planning/milestones/v4.24-version-matrix.md+ human-facingdocs/architecture/version-matrix.md) pinning the newest-stable target for Ruby, Rails, Node, Vue, vue-router, Vite, TypeScript, vue-tsc, vitest, and vitepress across all 7 packages — the source of truth every phase converged against. - Node normalized to 24 (Active LTS) across every
.nvmrc, everypackage.jsonengines.node, and both Node-based Dockerfiles (agent_runner,ionic_frontend) — up from a mixed 20/22 split. Ten CI steps stay deliberately pinned to Node 20 for theirfirebase-tools deploycall (firebase-tools#10726, an upstream WIF/ADC bug on Node ≥22, not repo drift). - Three per-major cost-benefit verdicts, each written against
ionic_frontend's actual config rather than the abstract changelog: vue-router 4→5 POSITIVE (no breaking changes for this app's router usage), TypeScript 5→6 POSITIVE (small, contained fix), Vite 7→8 NEGATIVE (three named breaking changes plus Capacitor/PWA-elements risk on the app that ships production mobile builds). - Ruby bumped to 4.0.6 in
rails_api. Rails was already at the pinned 8.1.3.1 from a prior security patch, so this phase touched zero application code. design_systemconverged first (the shared foundation) — vue-router 4.6→5.2.0, TypeScript 5.9→6.0.2, plus the rest of the matrix — with its public API surface (tailwind-tokens.cjs,css/tokens.css) verified untouched before its consumers upgraded.admin_dashboard(light bump) andionic_frontend(the heavy lift) converged in Phase 4.ionic_frontendcrossed both POSITIVE majors — vue-router 4.2.0→5.2.0 needed zero code changes; TypeScript 5.9→6.0.2 plus vue-tsc 3's stricter checking surfaced two real latent type gaps, fixed rather than suppressed — and deliberately stayed on Vite^7.3.5per the NEGATIVE verdict, re-confirmed to still build and test clean against every other bumped dependency.agent_runnermoved to TypeScript 6.0.2 on the node-24 Docker toolchain Phase 1 already set up; its floatingvitest/viteranges (pinned to exact versions in Phase 1) stayed pinned, no floats reintroduced.docs_siteandguide_sitemoved to vitepress2.0.0-alpha.18+ Vue 3.5.40, deliberately staying on the 2.0 alpha track rather than "upgrading" to npm'slatest1.6.4 tag, which would have been a downgrade off the track both sites intentionally run.- Desi's post-upgrade visual-smoke pass on
admin_dashboardandionic_frontend: PASS, no unaccepted regressions in light or dark mode.
Phases
| Phase | Name | Status | Plans | Highlights |
|---|---|---|---|---|
| 1 | Foundation — target matrix, Node normalization, cost-benefit gate | Shipped | 1 | Version matrix committed; Node respec'd 22→24 mid-phase (Josh-approved); 3 verdicts locked; agent_runner floats pinned |
| 2 | Backend — Ruby + Rails | Shipped | 1 | Ruby 4.0.2→4.0.6; Rails already at target; RSpec 6081 green, 92.86% coverage |
| 3 | design_system toolchain | Shipped | 1 | Both POSITIVE majors crossed; public API surface verified zero-drift for consumers |
| 4 | admin_dashboard + ionic_frontend | Shipped | 2 (4a/4b split) | ionic_frontend crosses both POSITIVE majors, deliberately holds Vite 7; Desi visual-smoke PASS |
| 5 | agent_runner + doc sites | Shipped | 1 | agent_runner → TS 6.0.2; doc sites → vitepress 2.0.0-alpha.18 |
Key Decisions
- "Latest" means newest-stable, with laggards pulled up to the most-advanced sibling already in the repo — not a hypothetical next major nobody runs. Locked by Josh at kickoff (OBJ-1891). This is why the matrix targets TypeScript 6.0.2 (the most-advanced sibling's pin) and not the newly-released Go-native TypeScript 7 line that nothing in the repo runs yet.
- The per-major cost-benefit verdict is a real gate, not a formality. Phase 1 wrote each verdict against
ionic_frontend's actual config; Phase 4 independently re-verified the Vite NEGATIVE verdict's premise still held before accepting the partial convergence, rather than trusting the Phase 1 writeup at face value. - Node target respec'd mid-milestone: 22 → 24. 22 is Maintenance LTS with ~9 months left before EOL — normalizing onto it would have front-loaded another forced Node bump almost immediately, defeating the point of a convergence milestone. 24 is Active LTS (EOL 2028-04-30) and every toolchain in the matrix already supports it. Josh-approved on Orion's recommendation, 2026-07-29.
ionic_frontendstays on Vite 7, by design. Itsvite.config.tshits three of Vite 8's named breaking changes (theesbuild→oxcrename,rollupOptions→rolldownOptions, the dropped object form ofmanualChunks) plus a fragile Capacitor/PWA-elements dependency-optimizer workaround not worth risking without dedicated device testing — on the one app that ships production mobile builds. This is a documented, deliberate partial convergence, not a silently skipped major.- Ten Firebase-deploy CI steps stay on Node 20, permanently, until upstream fixes it.
firebase-tools15.22.x's WIF/ADC credential exchange fails on Node ≥22 (firebase/firebase-tools#10726) — every other job in those same workflow files runs on 24.
Requirements Coverage
10 / 10 requirements satisfied (per v4.24-dependency-convergence-MILESTONE-AUDIT.md) — every phase's ROADMAP acceptance line verified met against its shipped diff, with no unsatisfied or orphaned items. This milestone has no standalone REQUIREMENTS.md; the milestone ROADMAP is the requirement source, per this repo's convention for informal Multica-crew milestones.
Outcomes
The repo now builds and tests every package against a single, committed version matrix instead of inferring "current" from whichever package happened to upgrade most recently. A future dependency bump has one target to converge toward, not seven independent drift trajectories. ionic_frontend's Vite 8 migration is deferred to a dedicated follow-up phase with real-device smoke coverage — tracked, not forgotten — rather than rushed into this milestone's timeline. Node 24 buys the whole monorepo roughly two more years of Active LTS runway before the next forced bump.
Tech Debt
- (Phase 5)
agent_runner/src/agent/runner.ts:89— a TypeScript 6 discriminated-union narrowing was suppressed withas anyrather than fixed. Non-blocking; worth a small cleanup follow-up. - (Phase 5)
agent_runner's node-24 Docker build is unexercised by CI until amaster/tag push (Docker builds don't run on PR CI). First real exercise was the post-merge Staging Deployment run; a manualdocker buildconfirmation is recommended. - (Phase 2, pre-existing) A
mobile-androidPlaywright-lane flake (21/156 failures) surfaced in Phase 2's post-deploy staging smoke — root-caused by Vicki as a pre-existing environment issue predating this milestone, not a regression. Owner: Tess. Not yet filed as a standalone issue as of this close. - (Phase 2, pre-existing)
rails_api/Gemfile.lock'sRUBY VERSIONstanza still readsruby 4.0.0(bundle installdoesn't rewrite it under the repo's~> 4.0constraint) — unrelated to this bump, closeable with a futurebundle lock --update-ruby.
Related Artifacts
- Roadmap: v4.24-dependency-convergence-ROADMAP.md
- Milestone Audit: v4.24-dependency-convergence-MILESTONE-AUDIT.md
- Version matrix (machine-of-record): v4.24-version-matrix.md
- Version matrix (human-facing): docs/architecture/version-matrix.md
- Merge PRs: #1875 (Phase 1) · #1878 (Phase 2) · #1879 (Phase 3) · #1881 + #1882 (Phase 4) · #1880 (Phase 5)
Related Commits
14c500548— Phase 1 foundation: version matrix, Node 24 normalization, cost-benefit gate (PR #1875)e0568f6b9— Phase 2: bump Ruby to 4.0.6 in rails_api (PR #1878)0a163cbd— Phase 3: converge design_system toolchain to v4.24 matrix pins (PR #1879)39f94a168— Phase 4a: admin_dashboard v4.24 toolchain convergence (PR #1881)28498cfff— Phase 4b: ionic_frontend v4.24 heavy toolchain convergence (PR #1882)b806e206c— Phase 5: agent_runner TS6 + doc-site vitepress/Vue align (PR #1880)
Last updated: 2026-07-30