Repository navigation
v5.40.0
Released 2026-10-29.
All 33 packages (@warlock.js/* and create-warlock) move to 5.40.0 together;
keep every family package on the same version. No breaking changes. This release makes
warlock check finish on large apps, makes the development server steadier and quieter,
brings Windows up to a tested platform, and adds turn control, context editing, spend
limits and approvals to the AI agent loop.
1. Breaking changes
- None. Two additions can surface in strict code; see the upgrade notes:
FinishReasonhas a new member"tool_stop", andhttp.log: truenow writes one summary
line per request instead of one line per phase.
2. warlock check finishes on large apps (core)
- On a large app the conventions step could run for tens of minutes at full CPU without
printing anything. Two causes are fixed:- The
.clientboundary rule (WL9022) re-read, re-parsed and re-resolved every shared
file for each controller, service, model and route it checked. Import chains are now read
once per run, and files known to reach no.clientmodule are never walked again. - Parsed syntax trees kept their parent links in shared lookup tables. With thousands of
trees alive, memory cleanup stalled for seconds at a time. The links now live on the nodes,
and the import rules reuse one parse per file.
- The
- On an app with about 7,500 source files, the conventions step now takes about 14 seconds.
- Progress lines.
warlock checkprints one line to stderr when each step starts and
ends, and the conventions step reports its milestones. stdout is unchanged, so--json
still prints only the report. - Per-rule time budget. Each convention rule may use 30 seconds over a run. A rule that
goes over is skipped for the remaining files and reported as aWL9026warning, instead
of hanging the command. SetruleBudgetMsin.warlock-check.json;0turns it off.
3. A steadier, quieter development server (core, web, fs)
- Spec and test files are never auto-loaded. Command discovery,
main,routes,
worker,eventsand locale files, and the standalonecascade migrateloader skip
*.spec.*and*.test.*files, so avi.mock()beside a command no longer breaks the CLI. - The first page after a restart waits for the compile. In development the page loader
timeout defaults to 90 seconds and starts only after a reload in progress has settled.
Production keeps 15 seconds; an explicitweb.loaderTimeoutstill wins. - Smaller reloads. Importers that reach a changed file only through
import typeare no
longer reloaded, only the changed files are re-read, and the+N modulescount is per file.
Adding files at boot no longer re-scans every tracked file. - Requests survive reloads. New requests wait while a reload runs; requests already
running get up to 5 seconds to finish. A request held longer than 15 seconds gets a503
withRetry-After: 2.putJsonFileand the typings manifest are written atomically. - Module singletons.
appSingleton(key, create, { dispose, disposeOnReload })keeps one
instance per process across reloads and across the copy that pages load through Vite, and
disposes it on shutdown. A secondsupervisor()for the same registry and owner in one
process returns the running supervisor instead of failing with a held lock. - Less log noise.
- With
web.moduleBoundary: "warn", each boundary violation prints once per dev session,
then a count of repeats. - With
http.log: true, each request writes oneinfoline
(GET /orders 200 12ms [request id]); the per-phase lines move todebug.
http.logPhases: "info"restores the old output. - AI tool schema lint takes
lint: { ignore: [codes] }per tool, in
ai.config({ toolLint })and onai.mcp(server, { lint }), and prints each finding once
per process.
- With
- App ready hook.
Application.onceBooted()/whenBooted()runs after every connector
has started; the docs now say when it fires.
4. Windows (process, core, fs, ai, web)
- Process supervisor.
- The guardian answers the resume request before it starts the program, so a slow start
can no longer time out the ownership check. observationTimeoutMsis a supervisor option: 2 seconds on Linux, 15 on Windows and
macOS. The timeout error names the option.pollIntervalMsdefaults per platform: 100 ms on Linux, 500 ms on macOS, 1.5 s on
Windows.- On Windows one long-lived helper answers every process lookup in batches, instead of two
PowerShell processes per lookup, and the launch gate polls the guardian pipe directly.
- The guardian answers the resume request before it starts the program, so a slow start
- Fixed on Windows: image variants answered 500 when the cache path went over 260
characters;warlock typecheck,warlock check --changedandwarlock inspectcould not
match the compiler's paths; the development model registry keyed a deleted model
differently; end-to-end browsers ignored their profile;warlock releaselinked
node_moduleswith a directory symlink, which needs administrator rights. ai.snapshot.sqlitestores haveclose(), so their database file can be removed.- The framework's own test suites for
fs,process,core,webandainow run on
Windows in CI.
5. AI agent loop (ai, ai-anthropic)
- End a turn after a tool.
stopAfterTools: [...],stopWhen(ctx)on the agent, or
endsTurnon a tool ends the run with no further model call; the finish reason is
"tool_stop". - Context editing.
contextEditing: { clearToolResults }replaces old tool results with
a placeholder before each trip, for every provider. Anthropic models use the provider's
native clearing. It runs beforecompaction, which still summarises. - Prices and spend.
ai.pricing({ tables })builds one overridable price list from the
provider tables.budget({ onSpend })reports spend after every call, and
scoped: { window: "all" }caps a session or a lifetime. - Approvals.
ai.human.approval()takes per-tool modes (allow,deny,ask) and
remember, so an approval can cover the rest of the session for that tool or those
arguments.
6. AI providers and tools
- xAI: calls that use native web or X search go through the Responses API; other calls
stay on Chat Completions (api: "chat" | "responses"to choose). - OpenAI: a call with
web_searchis sent to the Responses API automatically; a model
that cannot search fails with a clear error before any request. - Google:
googleSearchBudget(n)stops sending search oncenqueries were used. The
Gemini API has no per-call cap, so one running call can still go over. - Model listing: every first-party adapter implements
models(), a live listing in one
shape (ModelInfo). - Workspace patches:
@warlock.js/ai-workspaceadds an atomicapply_patchtool for
unified diffs (modify, create, delete, rename), confined to the workspace.
7. Other fixes
- Manual
beginTransaction()covers the caller's queries (cascade). After
await beginTransaction(), the queries the caller runs use the transaction until commit or
rollback. Before, they ran outside it on MongoDB and on other pool connections on
PostgreSQL.transaction(fn)is unchanged. - New API-only projects typecheck (
create-warlock). A project created without web pages
no longer receivessrc/config/web.ts, which imported a package it does not install. - New projects tell agents how to upgrade (
create-warlock). The generatedAGENTS.mdhas an
"Upgrading Warlock.js" section: readnpx warlock release-notes --from <current>(bundled with
core, so it works offline), runnpx warlock update, follow the upgrade notes, then
npx warlock check. It also explains that each package's skills arrive as one router skill.
8. Upgrade notes
- Update the family. Run
npx warlock update. - Read what changed. Run
npx warlock release-notes --from 5.39.2. - Run
npx warlock check. It should now finish on a large app. AWL9026warning names
a rule that ran out of time; raiseruleBudgetMsif your app needs more. - Exhaustive
FinishReasonswitches. Add a"tool_stop"case where you switch over
every finish reason. - Request logs. If you rely on per-phase request lines at
info, set
http.logPhases: "info". - Replace app workarounds. Module-level singletons kept on
globalThiscan use
appSingleton(). A pinned longer ownership timeout or poll interval on Windows can usually
go. Specs moved away from command folders can come back. - Review manual transactions. Code that calls
beginTransaction()now runs its later
queries inside the transaction, as the API always promised. Make sure each one commits or
rolls back.