Aquí hi ha 11 versions de Common Agent Runtime, des de 14 de juny del 2026 fins a l’actual, 0.56.1. Cadascuna enllaça amb els instal·ladors del mateix desenvolupador.
| Versió | Data | Mida | Fitxers |
|---|---|---|---|
| 0.56.1Darrera versió | 7 d’octubre del 2026 | — | 64 bits ZIP Notes de la versió## v0.56.1
### Changes
• A2A tasks created by a CAR peer are owned by its full-key principal (`peer:<key>`), not its 4-byte fingerprint label, so two keys sharing a label cannot read, list, cancel, or continue each other's tasks. `RuntimeScope.caller_id` and the eventlog's `caller_id` carry the same principal. Tasks live in memory only, so no stored owner needs migrating (#2312).
• Peer-message and tool admission read the agent-permission policy chosen by their server state's `ServerStateConfig::agent_permissions_path`. The daemon default is unchanged:the operator's live `<CAR_HOME>/agent-permissions.json`, whatever `--journal-dir` is. Embedders can set `with_agent_permissions_path`, and `car-server-core`'s own unit tests use their tempdir's file. Before this, three `lattice::tests` failed on any Mac whose real policy held or denied an agent named `milo` (#2308).
• Keep builder sessions alive on macOS and Linux while a silent model-invoked `shell` process tree is doing measurable CPU work, using the same sampler, cadence, and one-percent-of-one-core threshold as protected checks. Truly idle silent commands still become stale.
• Preserve a bounded, credential-redacted stdout/stderr tail under each coder session's `evidence/shell` directory when a builder `shell` call times out or is cancelled, while continuing to terminate its complete process tree so build locks are released.
• **Your default org now applies to coding sessions, on any local engine.** `coder.start` (and `car code`) binds a session to your default org (`car auth default-org`) when you name no org and the repository declares none. A bound session can now run Claude Code, Codex or local Foreman, not only the native engine. Those engines always run isolated when bound:the CLI loads none of your own MCP servers, plugins, settings or memory, so organization work cannot leak into personal state, and it has no web access; Gemini and mini-swe-agent cannot isolate and refuse when bound. A default that cannot be used — a `distributed` run (fleet workers do not carry an organization yet), a default no login holds any more, or a failed membership check (offline, revoked) — refuses the start and tells you to pass `personal: true`; nothing silently runs as personal.
• A Lattice review mirrored onto host approvals no longer carries the review text. Approval rows are readable by every session, so the row holds only who asked whom and a summary of at most 120 characters; the full text stays on host-only `lattice.requests`. `host.resolve_approval` decides such a row only with `approve` or `deny`, since that word is passed back to the asker as the person's answer (#2299).
• **Organization-bound coding sessions stop calling the issuer on every step.** A session bound to an organization re-checked membership with the Parslee issuer at start, twice per turn, on every tool call and before every check — each an HTTPS round trip. A successful admission receipt is now reused until the issuer's own expiry on it (at most 30 seconds, counted from when the request was sent), per organization context; any denial or failure drops it immediately, so revocation still takes effect within 30 seconds. Removing a login or signing out through the daemon drops its cached admissions at once, and a slow success can never overwrite a newer denial.
• **Your machines under any of your logins are trusted peers.** Device discovery already covered every signed-in Parslee login (#2318), but only machines under the boot login were trusted, so a machine signed in under another of your logins could be seen but not messaged or handed fleet work. Trust now follows discovery. What it rests on is a login signed in on this machine plus the shared sync passphrase — so signing in a login that is not yours extends trust to its devices. Fleet work still spends one shared budget. Removing a login (`auth.remove_account`) or signing out (`auth.logout`) through the daemon withdraws its machines' trust before the call |
| 0.55.0 | 21 de setembre del 2026 | — | 64 bits ZIP Notes de la versió## v0.55.0
### Changes
• A confirmed build plan can shorten the agent-build deadline but can no longer remove or extend it past `[coder] max_agent_build_wall_secs`.
• Stop agent builds immediately on non-retryable model admission, credential, account, missing provider key, routing, and gateway failures, and show the inference recovery text instead of retrying or scoring a scenario mismatch.
• The macOS agent builder now shows live build attempt, phase, scenario, model, and elapsed-time progress against the deadline; timed-out builds explain what happened and offer Try again with the answers kept, and completed scenario checks show Passed.
• When approving a build plan in the macOS agent builder does not come back cleanly and CAR then finds the build session was abandoned, the builder keeps the setup answers on the template list, ready to resume, instead of showing a "could not verify that the build plan was approved" failure screen (#1522 follow-up).
• Agent Builder drafts now persist with registered agents, and rebuilding an existing agent preserves its id plus one prior spec for safe revert.
• The macOS agent builder's review screen now keeps "Create build plan" visible at any scroll position and window size:it sits in the persistent bottom bar beside "Cancel setup" instead of at the end of the scrolling review, and the builder's scroll indicator is always shown.
• When an agent build stops because the account is signed out or rejected, the builder now says so, offers Sign in, and lets you try again with the same answers.
• Stopping an agent build now keeps the answers you wrote:the New Agent screen offers "Continue your draft" and a retry starts a fresh build, instead of clearing all seven fields. Cancel setup still discards them, and now asks first.
• Leaving the agent builder now asks before it throws away answers you wrote:"Back to Agents", "Cancel setup" and "Start fresh" all confirm first — including "Start fresh" on the failed, timed-out and sign-in screens, where the build session is still attached — so a stopped build's parked setup cannot vanish on one stray click.
• `car agent new` now documents its 64-character safe project-id limit while continuing to use the full description for generated identity, goals, and scenarios.
• `car agent run` now prints CAR's goal verdict after the agent's reply (`goal check passed:<check> (N iterations)`, or `goal marked met without a check result`), and when the agent used tools it notes on stderr that the run's temporary workspace was removed when the run ended.
• The daemon now logs how each `declagents.invoke` run ended (agent id, turns, tool calls, goal met/grounded/iterations, and any error), never the input or output text.
• The Android host now treats the daemon's terminal `auth_required` frame as the end of the turn and shows its sign-in message in the assistant bubble — as a calm notice, not an error banner or notification — instead of holding an empty "Parslee Core is working on it..." row for 120 seconds and then showing nothing.
• A finished Android chat turn ignores every later event for that turn, so a `token` delivered behind a terminal frame can no longer append to a closed bubble, and a goal-bearing turn that ends signed out clears its pending "Checking:..." verification line.
• Sparkle appcast publishing now keeps a content-pinned `sign_update` tool outside disposable Swift build artifacts and preserves its diagnostics in detached release logs.
• **The assistant's project `deny_tool` test no longer fails when host tool availability changes mid-run.** It previously compared two separately discovered tool catalogs, so a host-dependent tool appearing between the control and policy runs failed the comparison. The assertion now reads a single runtime's model-visible and registered surfaces, still proving the denied tool disappears from the model catalog and delegate grants while staying registered for a policy refusal, and that unrelated built-in tools r |
| 0.54.0 | 15 de setembre del 2026 | — | 64 bits ZIP Notes de la versió## v0.54.0
### Changes
• Releases can now refresh the built-in model catalog's per-token prices from the Artificial Analysis aggregate (https://artificialanalysis.ai/), which republishes each vendor's own list prices. Base input and output prices feed model routing's cost term and its cost-budget filter, and were previously hand-entered and left to drift. Prompt-cache rates, which no catalog entry carried, make the cost figures in `car`'s usage display exact instead of approximations bounded by the base input rate. Only curated model joins are written, and the step is skipped when no API key is configured.
• Both catalog-writing release steps now replace the file atomically, so an interrupted write can no longer leave a truncated `builtin_catalog.json` for the release commit to pick up.
• Document historical draft proposals for Advisor live wiring and offer exchange; these proposals do not represent implemented runtime behavior.
• Enforce the agent builder's advertised end-to-end deadline, report live phase/model/attempt/scenario/elapsed progress through `coder.get`, and end timeouts with actionable `budget_exhausted` state.
• Mark `agent_scenarios_pass` passed when an agent build succeeds instead of leaving the builder contract pending.
• Stop an agent build's scenario turns at their next turn boundary on `coder.cancel`, and show the model serving the current repair or scenario instead of the spec-generation model.
• Stop offering the Parslee platform tools (`parslee_capabilities`, `parslee_m365_generate_document`) to a generated agent's build unless a Parslee account is signed in, so a signed-out local build is no longer derailed by `car auth login` guidance flowing back through its scenario checks; signing in and rebuilding offers them again.
• Agent builder:choosing another starting point now keeps the answers you wrote instead of silently erasing them; a "Continue your draft" action returns to them, and a stopped or abandoned build parks its answers for a retry instead of losing them.
• "Continue your draft" and the replace confirmation appear only for answers you typed yourself — an untouched template is not a draft.
• Picking a template while a draft with answers is waiting asks for confirmation before replacing them; the Home research starter no longer auto-picks its template over a waiting draft.
• Leaving setup ("Back to Agents" or cancel) still clears everything.
• `car agent new` no longer mints over-long agent IDs:ids derived from long descriptions are now capped at 64 characters (well under the 128-character peer-name limit that agent registration enforces) and suffixed with a 64-bit digest of the full name, so a long description always yields an ID that every CAR surface accepts and two different long descriptions are kept apart with collision-resistant odds (car#1492).
• The daemon now keeps token-bearing per-agent `manifest.toml` files owner-only on Unix and repairs permissive files and directories from older releases before loading them.
• `car agent new` now accepts long descriptions without creating overlong project directory names, while keeping the complete description as the agent builder's input.
• Clarified that a managed project's committed `agent.json` is build output and the daemon runs the separately registered `declagents.json` copy.
• **Supervised agents can now receive read-only daemon credentials.** Add `method_allowlist` to an `agents.upsert` record or external-process `manifest.toml` to restrict that agent token to named non-host daemon methods; excluded calls are rejected before dispatch, while registrations without the field keep their existing access.
• Kept `car agent new` successful during CLI/daemon version skew by falling back to the CLI's declarative registry path when an older daemon omits `registry_path`; `car agent where` now surfaces declarative lookup failures, emits daemon-canonical IDs in JSON, and `car info` marks corrupt declarative state unavailable instead of rep |
| 0.53.0 | 10 de setembre del 2026 | — | 64 bits ZIP Notes de la versió## v0.53.0
### Changes
• **Four holes around the peer surfaces, found while designing the receiving-side
broker and fixed together.** (1) A trusted peer could register a push-notification
webhook on the peer-authenticated A2A listener:send text, take the task id, point
`tasks/pushNotificationConfig/set` at a URL you control, and the host POSTs full
task snapshots — messages and artifacts — to it with no allowlist. A push config
is outbound authority, so it is refused on a messaging-only surface. (2) `a2a.start`
bound any address it was given while serving `NoAuth` (there is no auth parameter —
`build_router` hardcodes it) and registering the agent-basics filesystem tools, so a
reachable bind published `write_file` to anyone who could route to the port. A
non-loopback bind now requires `allow_non_loopback_bind:true`, the same explicit
opt-in `a2a.peers.add` and `a2a.send` already demand of their endpoints; a wildcard
bind is refused as the most reachable of all. (3) `agents.chat` reached an agent
with no channel guard and no policy, so it was the way around `agents.message`:
an agent denied at the `read_only` tier could chat at its target instead, and two
agents could answer each other with nothing to terminate the loop. Agent callers
now pass the same admission, sharing one dedupe window and rate budget per
recipient across both methods — a synchronous turn stays out of the in-flight
`QUEUE_CAP` count, which is a concurrency bound and not the backlog its old doc
comment claimed. The host stays exempt:it is the operator's own client, and the
dedupe window would otherwise swallow a person retyping a prompt. Admission runs
after the target is known to exist, so an unroutable id can neither burn the
dedupe window (whose refusal says "already delivered", which would have been
false) nor mint a permanent guard entry. (4) The same admission now covers the
paths that would otherwise be the way around *it*:`declagents.invoke`,
`declagents.route` and `declagents.route_split` reach the same declarative
executor, and the A2A conversational responder (`chat_collect`) reached a live
agent with no guard, no policy and no audit at all. Every refusal is written to
the peer audit journal with its outcome, which matters now that the budget is
shared — an `agents.message` refused for rate could have had its budget drained
by chat traffic, and without a record there is nothing to show where it went. Two more in the same family:`agents.chat.cancel`
removed a live turn's routing entry with no ownership check at all, while
`agents.chat.approve` in the dispatch arm beside it has always required the
originating host session — so any authenticated session could abort anyone's
turn by observing a `session_id`; and the peer-authenticated router now forces
`require_identity`, which is free because the middleware inserts an `Identity`
for every request it admits, and means a future reordering that dropped it
fails closed rather than quietly serving unattributed requests.
• **A peer trusted enough to message this host could write files on it.** The
peer-authenticated A2A listener binds this host's LAN address by default, and
its dispatcher ran on a `Runtime` that `register_agent_basics()` had stocked
with `write_file`/`edit_file` — with no `CapabilitySet`, no authz stage and no
admission gate, because every gate that answers "what may this caller do"
lives on the WebSocket surface instead. An inbound `Part::Data` carrying a
`tool` key compiles to a real `ToolCall` (`car-a2a::bridge`) and executes
*before* the `ChatResponder` is consulted, so `agent_reply_for`'s
"conversational" check never saw it. Adding a peer with `a2a.peers.add` — a
decision that reads as "let this daemon talk to me" — therefore also granted
filesystem write. That listener is now messaging-only:an action-bearing
message is refused with `-32600` before a task is created, and its runtime
registers no tools at all, so its public agent card stops advertising
filesystem skills to the LAN. P |
| 0.52.1 | 5 de setembre del 2026 | — | 64 bits ZIP Notes de la versió## v0.52.1
### Added
• **Deterministic self-healing signal detection core.** The new
`car-selfheal` leaf crate folds CAR's existing eventlog alerts/events and
supervisor snapshots into typed `Detection` records for metrics alerts,
exhausted/crash-looping agents, recurring level-token log errors,
silently-idle live agents, recurring cross-run tool failures, and capability
misses. Detection identity is `sha256(locator)` rather than scan
order; evidence and provenance are credential-redacted at capture time and
bounded before entering a record. Positive known-answer and negative
zero-detection fixtures calibrate every detector. The crate has no model,
network, I/O, filing, or remediation path — a detection is evidence, never a
work order.
• **Watch-only daemon self-healing detection and trusted local handoff.**
`car-server` now runs the five deterministic detectors immediately at boot
and every 15 minutes by default (`CAR_SELFHEAL_INTERVAL_SECS` changes
frequency only), using active event-log slices, supervisor snapshots,
bounded activity/stderr tails and activity-log metadata, and observe-only
registry state. `agent_log_errors.v1` flags a running agent only when its
activity tail repeats an `ERROR`/`FATAL`/`CRITICAL` level-token or traceback
signature, or when its activity mtime is stale beyond the threshold. INFO
lines that merely contain “failed” remain noise; timestamp/UUID/number
normalization and hour/day/week/month idle buckets keep deduplication stable.
New/changed detections, tick summaries, and operator dismissals append to the owner-private
`<CAR_HOME>/selfheal/detections.jsonl` ledger. Each tick also checks a bounded
list of local paths for a `.git` config whose origin is `Parslee-ai/car` (no
subprocess, network, or broad scan). A validated checkout routes detections
to one private, trusted-tier `<CAR_HOME>/selfheal/issues/<dedup-key>.md`
handoff document per key, updated on recurrence without writing into the
checkout. Invalid/absent candidates fail closed to ledger-only, with the
source path or refusal visible through `selfheal.status` and route/path on
`selfheal.detections`. The four RPCs are mirrored through Node/Python
bindings. No off-machine filing, proposal execution, restart, or remediation
path was added.
• **Operator CLI and trust policy for self-healing signals.** The new
`car selfheal` command wraps the daemon's existing watch-only RPCs:`status`
reports cadence, counts, and the resolved route; `list` filters and renders
active detections with route and local issue path; `show` prints a trusted
local handoff document; `dismiss` appends a suppression; and `run` requests
one tick. All shipped verbs fail non-zero when the daemon is unreachable.
Feedback filing controls remain absent until Parslee-ai/car#1137 lands.
`docs/self-healing.md` documents the source-presence gate, trusted versus
consumer triage tiers, and the cutover from the external Tank judge and
goalpool route.
• **Daily Continuity can publish unattended through one exact standing CAR
approval.** A host can grant `always_allow` to the literal
`(daily-continuity-newsroom, newsroom.publish)` pair, and CAR binds that grant
to the authenticated reverse callback's canonical schema digest. Future
admission succeeds only while the same agent, session, callback, and schema
remain attached; `car approvals set-tool`, `reset-tool`, and `evaluate-tool`
expose the lifecycle with stable audit provenance.
### Fixed
• **`verify-release.sh` now checks that the docs site actually deployed, not
just what it is serving.** Its appcast assertion had two causes for one
symptom:GitHub Pages still propagating (benign — the script's own comments
document a real v0.47.0 false positive) or the Pages *build* having failed,
which strands the release. Nothing distinguished them, and because the
documented cause is the benign one, a red read as flakiness. Cutting v0.52.0
it was the second — every registry held 0.52.0 while Sparkle could still only
see 0.51.0, and the only t |
| 0.51.0 | 31 d’agost del 2026 | — | 64 bits ZIP Notes de la versió## v0.51.0
### Changed
• **The coder's shell now holds no forge credential**, which is the one version
of "the model cannot publish" that does not depend on out-lexing `/bin/sh`.
The deny-list added in car#1074 is hardening, not a sandbox:it reads the verb
of each shell segment and then hands that segment to `/bin/sh`, so `sh -c`,
`env`, `timeout`, `$(…)`, a `\gh` escape, or a delegated `car do "…push it"`
all move or bypass the verb. No finite set of patterns closes that against an
unrestricted shell.
Credential separation has a different shape. `GH_TOKEN`, `GITHUB_TOKEN` and
their enterprise spellings are removed from the child; `GH_CONFIG_DIR` points
at an empty directory so `gh` cannot fall back to `~/.config/gh/hosts.yml`;
and git's `credential.helper` is overridden to empty for that child. That last
one is easy to miss and would have left the hole open on its own — `git push`
over HTTPS never reads `GH_TOKEN`, it asks the helper, which on a Mac is
perfectly happy to hand over a stored credential.
Every route then fails on **authentication** rather than on being recognised,
and because environment removal is inherited by the whole process tree it
covers the spellings the matcher cannot see. Delivery is unaffected:
`coder::merge` is host code that builds its own argv outside the model's shell
and keeps the real credential. The runtime publishes; the model cannot.
**Deliberate cost:** on a **private** repository the read allowlist
(`gh pr view`, `gh run view`, `gh api` GET) now fails unauthenticated, so a
session cannot watch its own CI there. Public repos are unaffected. Restoring
it means either a scoped read-only token for the coder shell or moving CI
observation into host code — both larger than this change, and neither done.
Contract checks keep their credentials:a check runs a command the contract
declares rather than one the model just wrote, and may legitimately need to
reach a real system (car#1066). The `run_shell` / `run_check_shell` split from
car#1065 is what makes that distinction expressible.
Closes #1084.
### Added
• **The coder now reads what the repository says about how to work in it**
(`CLAUDE.md` / `AGENTS.md`, and `.car/` project knowledge). Previously
everything a session knew about its repo was two lines from `summarize_repo`
— the top-level entries and which build files exist.
The rules that get a diff rejected are almost never expressible as an outcome
contract. "No cargo feature flags, ever" and "a change crossing the FFI
boundary updates five surfaces in the same change" are review-time rules; a
model that has not read them does the *normal* thing and produces a diff that
compiles, passes every check, and is rejected on sight. Contract-green and
mergeable are different properties, and only one of them was reaching the
model.
The block lands after `ENVIRONMENT:` and before the how-to-work rules,
because these are constraints on *how* the work is done rather than facts
about the machine. Its framing is load-bearing rather than decorative:it
states that the contract does **not** verify these rules, and that a check
must never be weakened or edited to satisfy one — the contract decides
whether the work is done, the instructions decide whether it is acceptable.
A repo carrying neither instructions nor a `.car/` project gets a
byte-identical prompt to before, and there is a test pinning that.
`.car/` discovery reuses `car_memgine::project`, which already walks up from
a starting directory the way `.gitignore` resolution does, so a session cut at
a subdirectory still finds the project.
**Delegation is handled by indexing, not inlining.** Instruction files point
elsewhere — this repo's `CLAUDE.md` says the full binding surface "lives in
the `car-bindings-api` skill". Handing the model a pointer it cannot follow is
worse than useless:it learns a rule exists without learning what it says. So
`.claude/skills/*/SKILL.md` frontmatter is indexed by name, one-sentence
description and **path**, wit |
| 0.50.0 | 25 d’agost del 2026 | — | 64 bits ZIP Notes de la versió## v0.50.0
### Fixed
• **`exit code 100` in a nextest step now has a name, and one place to fix
it.** Two runs failed on a step whose only annotation was `Process completed
with exit code 100` — no failing assertion, no test named, matching no known
signature. The real line sat in the job log:`fatal runtime error: stack
overflow, aborting`, aborting one arbitrary `car-server-core` test with
SIGABRT. The two runs died on two *different* tests, which is the tell:no
test was at fault. `handler.rs` is a single `async fn` dispatcher over 382
string-literal method arms, and in a debug build the resulting future is
megabytes wide — wider than the 2 MiB stack Rust gives the thread libtest
runs each test on. The tests passed until an unrelated change grew the future
a few hundred KB, then an arbitrary one of them aborted.
`RUST_MIN_STACK` now lives in the repo-root `.cargo/config.toml`'s `[env]`,
which cargo applies to every process it launches, from every cwd and on every
cargo version. Previously it was a step-level `env:` on the one CI step where
the overflow was observed, while the other seven invocations that run these
same tests — `coverage`, `shared-process-test`, the doctest step, two
`check-windows` steps, `build.yml`'s tag-time run and `ci-local.sh` — had no
protection. `coverage` is the one that went over:it failed on `main`'s
2026-08-25 nightly with the identical SIGABRT, and passes with this change.
No test, assertion or gate was changed; the process is given the stack the
code it exercises needs. `car-server-core/tests/stack_budget.rs` fails by
name if the budget is ever removed, rather than letting an unrelated test
abort months later.
`docs/solutions/nextest-exit-100-is-a-stack-overflow.md` carries the full
trail, including what to do when 8 MiB is not enough either.
• **A slow `build-windows` no longer strands a release half-published.**
`release.sh`'s Step-3 wait for CI to create the GitHub Release was a fixed
720 x 10 s = 120 min budget, sized off the slowest Windows build anyone had
measured. Cutting v0.49.0 that job took 2 h 6 m while legitimately
progressing, the budget expired on a healthy run, and everything downstream
of the wait — the signed macOS upload, the `preflight-macos-assets` gate, the
npm/PyPI publishes and the mirror, then the whole post-CI tail — silently did
not happen. Re-driving CI does not repair that, because CI does not own the
tail.
The wait is now adaptive:it asks the workflow run whether a job that could
still create the release is running. A healthy run keeps waiting past the old
two hours, and a run that reached a terminal state without creating the
release now fails in minutes instead of hours. A 6 h hard ceiling and a
soft budget (past which a run that reads non-healthy on five consecutive
minute-apart probes is fatal — one unreadable `gh` response is not, or a
rate-limit blip would strand the release the same way the clock did) keep it
bounded. Every failure path prints the exact recovery — the already-notarized
assets staged on disk are the resume point, `backfill-macos-assets.sh` is the
expensive wrong tool for this — and `scripts/test-release-ci-wait.sh` runs
the real loop against a canned `gh` on every PR.
### Added
• **The supervised assistant can now run a repository-scoped, durable,
governed host workflow without delegating its engineering loop to another
coding agent.** `car do --serve --governed-host --dir <repo>` binds host
toolchains and network access to an explicit Git repository, keeps
consequential actions behind exact-scope durable approvals, applies
project-defined deployment/database gates, checkpoints exact model history,
fences crash-boundary dispatch from replay, and emits hash-chained receipts
with local, remote, CI/CD, deployment, health, and browser proof reported as
separate stages. New sync checkpoint/action JSON-RPC and Node/Python binding
methods expose the durable records for audit and recovery.
• **Local models now have durable CAR ownership, resou |
| 0.49.0 | 24 d’agost del 2026 | — | 64 bits ZIP Notes de la versió## v0.49.0
### Security
• **A web page you had open could drive the daemon's MCP endpoint.** `POST
/mcp` and `GET /mcp` accepted any request that reached the port, and browsers
will happily send a cross-origin POST to `http://127.0.0.1:9102/mcp` on
behalf of whatever page is loaded — so any site could call `tools/call` and
read or write the user's memory graph. Binding loopback does not prevent
this:the browser is *on* loopback, and DNS rebinding defeats the bind on its
own. The MCP HTTP transport requires `Origin` validation for exactly this
reason and CAR had none.
Both routes now validate `Origin`, absent-permissive and present-strict. **No
`Origin` header is allowed** — a browser always sends one on a cross-origin
request, so its absence cannot be a browser attack, and this is what keeps
every real client working (`curl`, Claude Desktop, Cursor, Claude Code
`--mcp-config`, Codex, and CAR's own connectors client all send none). An
`Origin` naming loopback — `http`/`https` on `localhost`, `127.0.0.0/8`, or
`::1`, any port — is allowed. Anything else, including the opaque literal
`null` sent by sandboxed iframes and `file://` pages, gets `403
{"error":"origin not allowed"}` before the request reaches the dispatcher, so
the tool never runs.
`GET /mcp/health` is deliberately exempt:no side effect, no secrets, and the
documented uptime probe has to keep working. The rule does not widen for a
non-loopback `--mcp-bind` — front the daemon with a reverse proxy that owns
its own CORS policy if you need browser traffic from another origin
(Parslee-ai/car#972 §3).
### Fixed
• **`car-inference` could not link on any Xcode older than 26.** `build.rs`
emitted `-Wl,-weak_framework,FoundationModels` unconditionally on every Apple
target. `-weak_framework` controls how the *load command* is written — it is
not a link-time "optional", so `ld` still resolves the name against the
active SDK and hard-fails with `framework 'FoundationModels' not found` when
it is absent. Pre-26 SDKs do not ship it.
The Swift shim already handled that case:every FoundationModels code path
sits behind `#if canImport(FoundationModels)`, so on such an SDK the compiled
object references no FM symbols and the framework is not needed at all — the
two guards had simply drifted apart. `build.rs` now probes the SDK and emits
the link arg only when the framework is really there, with a `cargo:warning`
otherwise. All six `@_cdecl` entry points are declared outside those blocks,
so the static library still exports the full C ABI, `car_fm_swift_built`
stays set, and `car_fm_is_available` reports 0 — the adaptive router falls
through to another backend exactly as it does on pre-26 *runtimes*.
Nothing caught this because nothing linked the crate on an older SDK:the
Linux `test` job compiles no Apple code and `apple-checks.yml`'s macOS job
ran `cargo check`, which executes `build.rs` but skips codegen and linking.
The `cargo test` step added in Parslee-ai/car#971 is the first one that
links, and it failed on its first real run.
• **Five daemon JSON-RPC methods were dispatched but documented nowhere.**
`assistants.invoke`, `events.stats`, `events.truncate`, `events.clear`, and
`memory.build_context_fast` all worked, and appeared in neither
`docs/websocket-protocol.md` nor the `car-bindings-api` skill that calls
itself the canonical list. External developers consume CAR through those two
and have no access to the source, so an undocumented method is an
unreachable one. Found by a release-time sweep of every dispatch arm against
the docs; each is now written up with its real parameter and return shape.
Two of them deserved the words more than most:`events.clear` is destructive
and unconditional — it drops the whole session log including the
`events.query` audit trail and any `events.chain.enable` hash chain, with no
undo — and `memory.build_context_fast` returns facts in **creation order,
not relevance order**, which is easy to reach for by name and wrong for
anything that |
| 0.48.0 | 18 d’agost del 2026 | — | 64 bits ZIP |
| 0.47.0 | 9 d’agost del 2026 | — | 64 bits ZIP |
| 0.24.1 | 14 de juny del 2026 | — | 64 bits ZIP |