Repository navigation
Stability
From v30: at most one major every 90 days, the previous major gets security fixes for 6 months after its successor, and a removal is deprecated for at least one minor first. Each rule is refused by a script, not remembered by a person — the table at the bottom names the code.
Next major window: 90 days after the date on the ## 30.0.0 heading in CHANGELOG.md. Until v30 ships, this line names no date; bun run scripts/release-due.ts --json answers it as .data.windowOpensOn while a major waits.
A breaking change to any of these needs a major, and a major waits for its window.
| Surface | Where it is defined |
|---|---|
the eight primitive shapes: entity, policy, action, mutator, query, job, route, task
|
The eight primitives, PRIMITIVE_KINDS in packages/core/src/registrar.ts
|
the x CLI: every command, every flag, and the --json envelope each prints |
CLI reference |
every shipped X_* code: its name and its meaning. A code is never renamed or reused |
Error codes |
| the package tier table |
scripts/lib/tiers.ts, Project layout
|
app.config.ts field names: renaming or removing one |
Configuration |
every export a package's src/index.ts names and its README documents |
each package's README.md
|
| the Bun floor |
engines in every package.json; it moves only in a scheduled major, or by the security exception |
| Not covered | Why |
|---|---|
an export no README documents, and any deep import (@ultimat3/x/src/...) |
not a public surface; it can change in a minor |
.x/ — the build cache, generated manifests, snapshots |
regenerated by the CLI; never hand-edited, never read by an app |
the exact wording of a cause: or fix: line |
the code is the contract; the text improves in any release |
| a gate verdict getting stricter | a new x verify rule that reds an app waits on next like any break |
| performance figures and budgets | measurements, re-measured each release (Routes and render modes) |
Never "stable forever": a covered surface can change, in a scheduled major, with its entry in Upgrading.
| Bump | Means | Examples |
|---|---|---|
| major | a covered surface changed incompatibly | a removed config field, a renamed CLI flag, a changed primitive field, a narrowed tier |
| minor | additive: old code still compiles and still passes x verify
|
a new optional field, a new command, a new driver behind an existing interface, a new @deprecated alias |
| patch | no surface change | a bug fix, a perf change, a corrected fix: line |
| Release | When | Branch | npm dist-tag |
|---|---|---|---|
| major | at most once per 90 days from v30, counted from the previous major's CHANGELOG.md heading date |
next, merged into main when the window opens |
latest |
| minor | weekly, when something shipped | main |
latest |
| patch to the current major | as needed | main |
latest |
| patch to the previous major | security fixes only, until 6 months after its successor shipped | release/<major>.x |
maint-<major> |
| prerelease of the next major — planned, nothing ships one yet |
release-tag.yml cuts only X.Y.Z release commits, so no workflow publishes from next
|
next |
next (scripts/dist-tag.ts already names it) |
v30 is the exception that starts the clock: it carries every break queued before the promise existed, and scripts/release.ts does not refuse it.
| Major | Status | Security fixes until |
|---|---|---|
the current major (npm view @ultimat3/core version) |
every fix | its successor ships, then 6 months more |
| the previous major | security fixes, as patches on release/<major>.x
|
6 months after the current major's ## X.0.0 date |
| anything older | none |
Upgrading, one major per x upgrade run |
Convention, not enforced: release/<major>.x is cut by hand at each major and kept at that major's newest minor; no script cuts or checks it. Once it exists, a patch is latest while its major is current and maint-<major> once its successor ships. scripts/dist-tag.ts decides the tag from the registry's latest, and npm publish never runs without it.
A removal or a rename ships its alias, marked @deprecated, on main for at least one minor before a major takes it away. The rule compares each package's src/index.ts export names against the previous release tag: a name that is gone must have carried @deprecated there. Runtime deprecation logging is not part of this — it was deleted once, for good reason (Upgrading).
| Branch | Holds |
|---|---|
main |
minors and patches only while the window is closed; a BREAKING — changelog entry there is refused |
next |
every breaking change waiting for the window. Convention, not enforced: it merges main weekly, by hand, so it never falls behind a fix; ci.yml gates every push to it |
release/<major>.x |
the previous major's security patches |
A change with both kinds of edit splits into two pull requests: the non-breaking half to main, the break to next.
A security fix that cannot be made non-breaking may ship a major inside the window. It is the only exception — "critical bug" is not one, or it would be used every week.
bun run scripts/release.ts --bump major --security GHSA-xxxx-xxxx-xxxx --dry-run --jsonThe advisory id (a GHSA-… or CVE-…) is recorded under the section heading in CHANGELOG.md as > **Security exception:** \`, and the bump commit's body carries Security-Exception: `. The same recorded line lets a removal skip its deprecation minor.
The maintainer bot judges whether a release is due and which kind (.dz/briefs/release-due.md), inside this window: it cannot cut a major the window refuses, because scripts/release.ts refuses it before any file moves, release.ts --check refuses it again before a tag is cut, and the gate refuses a dated section that broke it.
| Rule | Refused by | Code |
|---|---|---|
| one major per 90 days |
scripts/release.ts --bump, --check, and the gate's boundaries step |
X_RELEASE_MAJOR_WINDOW |
no break on main while the window is closed |
bun run changelog-check and the gate, on the pull request's base branch |
X_BREAKING_ON_MAIN |
| a removal was deprecated first |
bun run scripts/deprecation-window.ts and the gate |
X_RELEASE_UNDEPRECATED_REMOVAL |
| every release from 30.0.0 opens with Highlights, the Release body |
bun run changelog-check and the gate |
X_CHANGELOG_HIGHLIGHTS_MISSING |
a maintenance publish never moves latest
|
scripts/dist-tag.ts in release.yml; scripts/registry-audit.ts audits latest and each maint-* tag |
X_REGISTRY_LATEST_DRIFT |
Ultimate — v29.4.0 As of 2026-10. The full-stack framework where the primary developer is an AI agent: bunx create-ultimate myapp → Getting started · live demo. MIT licensed. What npm serves is npm view @ultimat3/core version, never this line, and this footer is the only page that stamps a version.
Repository · Issues · Changelog · llms.txt
Edits to these pages are synced from wiki/ in the repository — change the file there, not the wiki, or the next sync overwrites it.
Start
Tutorials
- 1 · First app
- 2 · First feature
- 3 · Auth and admin
- 4 · Jobs and realtime
- 5 · Deploy free
- 6 · Growing up
Primitives
- The eight primitives
- Building your own base
- Actions
- Entities and migrations
- Policies and authz
- Queries and live queries
- Client data
- Jobs and workflows
- Scheduled tasks
- Routes and render modes
Capabilities
- Realtime
- Caching and invalidation
- Batching and preloading
- N+1 detection
- PWA and offline
- Client navigation
- MCP and AI
- Agents
- Admin dashboard
- Scraping
- Auth
- Notify
- Storage and uploads
- Feature flags
- SEO
- Static assets
Cross-cutting
- I18n
- Theming
- UI components
- Interface rules
- Timezones and dates
- Money
- Outbound HTTP
- Resource management
- Migrations and backfills
- Testing
- CI: the gate across parallel jobs
Reference