v2.13.8
Forge v2.13.8
CLI/TUI and desktop release v2.13.8; mobile remains on its compatible native version.
- CLI / TUI — binaries below (
*.tar.gz/*.zip) orbrew upgrade forge - Desktop (macOS · Windows · Linux) — app bundles below + in-app auto-update
- Mobile (iOS) — production OTA by default; native/TestFlight builds are manual when required
Fixed
-
A long tool loop threw away the task it was working on. When the transcript overflowed the
model's window, the fit kept every system message and a newest-first suffix of history — and the
user's own message was neither, so a tool loop that filled the budget evicted the instruction
while keeping the output it produced. The model then reported that no task had arrived and
invented work from what was left. The newest user message is now reserved before the walk, and
clipped rather than dropped when it alone exceeds the budget (crates/forge-core/src/context_pipeline.rs). -
A model behind a gateway assumed a 32k window when its real one is a million tokens. OpenCode
Zen and Go list models without a context length, as do most custom OpenAI-compatible endpoints, so
every model behind one fell to the conservative floor and trimmed long turns for no reason. A
model with no window row of its own now inherits the window published for the same model under
another namespace, lowest match winning (crates/forge-mesh/src/pricing.rs,
crates/forge-core/src/routing_policy.rs). -
An explicitly read-only turn was re-driven to produce a diff. A worktree-backed daemon session
arms a code-change expectation for its whole life, and that beat the prompt, so a turn that said
"do not edit anything" ended with no edits, tripped the empty-diff guard, and was pushed to
"implement the fix now". An imperative read-only instruction in the prompt now wins, and the
phrase list recognises what an operator actually types (crates/forge-core/src/turn_contract.rs). -
OpenCode Zen's Responses-only models could not be called at all.
muse-*,gpt-*andgrok-*
answer only on/responsesthere, while Forge always built an OpenAI-chat request and got an
instant 500. Zen now reuses the per-model wire-format matrix the Go adapter already carries
(crates/forge-provider/src/genai_provider.rs). -
A new model silently inherited an older sibling's benchmark score. The cross-version guard
compared version numbers by membership, so a shared major digit let a different minor through:
muse-spark-1.3matched "Muse Spark 1.2" on the shared1. Comparison is positional now, and a
benchmark row missing one of its two indices is kept on the index it has rather than dropped
(crates/forge-mesh/src/bench.rs,crates/forge-cli/src/benchmarks.rs). -
An Ask temper on the CLI bridge approved silently instead of refusing. A bridged turn had no
one to answer a permission prompt, so the gate resolved the wrong way
(crates/forge-core/src/permission.rs). -
Routing stalled on rediscovery when a cached catalog already existed, and the daemon's models
page served the last terminal's catalog rather than its own
(crates/forge-cli/src/cli/commands/models/discovery.rs,crates/forge-cli/src/serve/serve_models.rs). -
An over-pace subscription pool is now held entirely, and the last-resort override is
re-checked per failover hop instead of being spent once and left open
(crates/forge-mesh/src/lib.rs,crates/forge-core/src/model_request.rs). -
An unattended bridge turn that stalled with tasks still open now fails instead of reporting
success (crates/forge-core/src/turn_guards.rs). -
An explicitly configured
[mesh.models]tier is honoured over an auto-discovered one
(crates/forge-mesh/src/catalog.rs). -
forge doctorreports a provider-rejected key as invalid rather than unreachable, and
forge modelssays which listed models have no key
(crates/forge-cli/src/doctor_health.rs,crates/forge-cli/src/cli/commands/models.rs). -
A keyless first run skips network enrichment, bare
forgeshows a first-run panel instead of
the full command list, non-tty setup is actionable, and CLI bridges known to be logged out are no
longer probed (crates/forge-cli/src/cli/commands/run.rs,crates/forge-provider/src/lib.rs). -
Claude quota is read from
unifiedWindows, and model reasoning is no longer printed as answer
text on a non-tty (crates/forge-provider/src/claude_quota.rs,crates/forge-tui/src/lib.rs). -
Opt-in: a standalone
forge runcan execute in the daemon and show in the Anywhere fleet.
[remote] publish_local_runs(default off) and per-run--publish-to-fleet/
--no-publish-to-fleethand the prompt to the local daemon, which creates a session carrying the
cwd, model and a title from the prompt's first line. A one-shot run was previously invisible to
the phone however healthy the relay was. Failure is soft: no daemon means the run proceeds locally
exactly as before. Output is not streamed back to the handing terminal, which prints the session
id and theforge attach <id>command (crates/forge-cli/src/cli/commands/run/one_shot.rs). -
The empty-diff nudge and the code-change classification read the turn's contract, not the
session-wide flag a worktree daemon session arms for its whole life, so an explicitly read-only
turn is no longer re-driven with "implement the fix now" (crates/forge-core/src/lib.rs). -
forge runno longer stalls on rediscovery when a cached catalog exists, and one reader now
serves both the router and the daemon's models page
(crates/forge-cli/src/cli/commands/models/discovery.rs). -
The mesh explanation marks a rank a routing rule decided instead of restating the score as
something it is not (crates/forge-mesh/src/explain.rs).
Added
POST /api/sessions/{id}/interruptends a fleet session's current turn and leaves it live and
idle. The daemon accepted an interrupt over its WebSocket but had no HTTP route, so a script could
only stop a runaway turn by ending the session;--steeris no substitute, since it lands at the
next turn boundary and a session stuck in a tool loop never reaches one (crates/forge-cli/src/serve.rs).
Changed
release-buildno longer gates pull requests. The release compile plus its upgrade,
reconnect and rollback end-to-end is the longest job in the pipeline, and every heavy job
serializes on one runner, so running it per pull request set the merge throughput of the project.
It runs on the push to main after a merge, on the weekly schedule, and on the dispatch the release
workflow fires — still before anything ships (.github/workflows/ci.yml).
What's Changed
- chore(dist): update package manifests to v2.13.7 by @github-actions[bot] in #1245
- fix(provider): read claude quota from unifiedWindows, not a top-level field that no longer exists by @florisvoskamp in #1244
- fix(tui): don't print model reasoning as answer text on a non-tty by @florisvoskamp in #1242
- fix(cli): bare
forgeshows a first-run panel, not the 40-command help wall by @florisvoskamp in #1250 - fix(onboarding): make the keyless first run and non-tty setup actionable by @florisvoskamp in #1248
- fix(provider): stop probing CLI bridges that are already known to be logged out by @florisvoskamp in #1251
- fix(cli): forge models says which listed models have no key instead of implying a keyless install is ready by @florisvoskamp in #1247
- perf(startup): skip network enrichment on a keyless run and memoize keyring reads by @florisvoskamp in #1252
- fix(doctor): report a provider-rejected key as invalid instead of "usable" by @florisvoskamp in #1249
- fix(mesh): honour an explicitly configured [mesh.models] tier over auto-discovery by @florisvoskamp in #1253
- ci(release): automate the install/upgrade-path verification for RELEASING.md §7 by @florisvoskamp in #1255
- fix(core): fail an unattended bridge turn that stalls with tasks open by @florisvoskamp in #1256
- chore(core): keep model_request.rs under the size guard after #1248 and #1251 landed together by @florisvoskamp in #1258
- fix(mesh): hold an over-pace subscription pool entirely, cap the last resort to one hop, keep over-pace Go windows by @florisvoskamp in #1261
- ci: release-build stops gating pull requests by @florisvoskamp in #1265
- fix(bridge): an Ask temper on the CLI bridge must refuse, not silently run the tool by @florisvoskamp in #1259
- fix(core): an explicitly read-only turn is not re-driven to produce a diff by @florisvoskamp in #1266
- fix(serve): /api/models serves the daemon's live catalog, not the last terminal's by @florisvoskamp in #1254
- fix(core): a long tool loop can no longer evict the turn's task statement by @florisvoskamp in #1263
- fix(mesh): a gateway model inherits the context window published for it elsewhere by @florisvoskamp in #1264
- fix(mesh): route OpenCode Zen Responses-only models; stop 1.3 inheriting 1.2's bench score by @florisvoskamp in #1262
- feat(serve): interrupt a session's current turn over HTTP by @florisvoskamp in #1267
- fix(mesh): mark ranks a routing rule decided, keep the score honest by @florisvoskamp in #1246
- fix(mesh): route from the cached catalog instead of stalling on rediscovery by @florisvoskamp in #1257
- docs(changelog): record everything merged since v2.13.7 by @florisvoskamp in #1268
- feat(run): opt-in — a standalone
forge runcan execute in the daemon and show in the fleet by @florisvoskamp in #1269 - fix(core): the empty-diff nudge reads the turn's contract, not the session flag by @florisvoskamp in #1270
- chore: prepare v2.13.8 release by @florisvoskamp in #1271
Full Changelog: v2.13.7...v2.13.8