From 96dd68af064f3bcb46cbfc107cb27138b113a89c Mon Sep 17 00:00:00 2001 From: Kishore Kumar Date: Sat, 1 Aug 2026 06:33:47 +0530 Subject: [PATCH 1/2] docs(changelog): a runner you assign now runs the work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A host could show Active and Online, take an isolation assignment, and still fail every job: the daemon never enabled the resource controllers systemd delegated to it, and the sandboxed child had no HOME to resolve its configuration from, so each lease died at startup with UZ-EXEC-012 and no cause in the journal. Eight bullets across the two surfaces an operator touches — the failures themselves, and the dialog that assigns the policy. No page revisions: no published page documents the unit file, the isolation tiers, or the chat failure copy, so the entry is the whole user-visible surface. Co-Authored-By: Claude Opus 5 (1M context) --- changelog.mdx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.mdx b/changelog.mdx index e8b9fed..7b8cb5d 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -7,6 +7,26 @@ description: "Stay up to date with the latest agentsfleet product updates, new f agentsfleet is in **stealth-mode testing** and pre-production. APIs and agent behavior may change between releases without long deprecation windows. Email [agentsfleet@agentmail.to](mailto:agentsfleet@agentmail.to) if you want a hand calibrating an agent or to join as a design partner. + + ## A runner you assign now runs the work + + A host could show **Active** and **Online**, take an isolation assignment, and still fail every job handed to it. Two faults stacked: the daemon never enabled the resource controllers systemd had delegated to it, and the sandboxed child had no `HOME` from which to resolve its configuration — so each lease died at startup with `UZ-EXEC-012` and the journal named a code and no cause. Controllers are now enabled when the daemon starts rather than when its first assignment arrives, `agentsfleet-runner.service` supplies the `HOME` the child needs, and a host that cannot enforce limits is refused before it is given a runner at all. + + ## Bug fixes + + - **Every lease died at initialization when the service had no `HOME`.** systemd gives a service with no `User=` no home of its own, and the sandbox forwards `HOME` only when the daemon holds it, so the engine could not resolve a configuration directory. The unit now sets it to its own `RuntimeDirectory`, which `ProtectHome=yes` and `ProtectSystem=strict` leave reachable where `/root` would not be. + - **Resource controllers are enabled at daemon startup, not on the first assignment.** `Delegate=` makes `cpu memory pids` available to the unit, but writing `cgroup.subtree_control` is the delegatee's job and systemd never does it. Doing it at startup means a runner with no assignment yet still enables them, and the post-deploy check no longer races the first heartbeat. + - **A failed configuration load names its cause.** The error was discarded before it reached the log, leaving `UZ-EXEC-012` with nothing to act on; the record now carries the underlying failure. + - **Execution cgroups are removed when a lease ends.** Teardown used a recursive delete, which the kernel refuses because the control files inside a cgroup cannot be unlinked — so every reclaim failed and the directories accumulated on the host for the life of the runner. + - **An unrecognised runner failure is no longer blamed on the fleet.** A cause the chat surface could not classify fell back to "this fleet needs instructions" and appended the internal error name. A cause that is not operator-facing prose now reads as a runner failure, and the identifier is not shown. A fleet that genuinely has no instructions still says so. + - **A host that cannot enforce limits is refused before deployment.** The readiness check ran only after the runner was installed, and stopped at the first missing controller — so a host missing all three reported one. It now names every missing controller in a single run and verifies the kernel and `system.slice` before the deploy proceeds. + + ## Assigning a policy + + - **The policy dialog scrolls.** Its actions sat below the fold on a short viewport with no way to reach them, so assigning a policy required maximising the window. + - **The three isolation tiers sit on one row.** Two columns wrapped the third onto a row of its own. + + ## Every runner lease says whose workspace it belongs to From cc13814230f42df1a9e86899bafea055800ae1bb Mon Sep 17 00:00:00 2001 From: Kishore Kumar Date: Sat, 1 Aug 2026 14:50:25 +0530 Subject: [PATCH 2/2] =?UTF-8?q?docs(m156):=20changelog=20=E2=80=94=20the?= =?UTF-8?q?=20free=20trial=20ends=20per=20account,=20not=20on=20a=20calend?= =?UTF-8?q?ar=20date?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second Aug 01 entry for the §7 fold-in: the boundary moved off a build-time constant onto billing.tenant_billing.free_trial_ends_at (NULL = open-ended), free_trial.ends_at_ms went nullable on GET /v1/tenants/me/billing, and the pricing surfaces stopped printing a date. Tagged Breaking for the wire-shape change; pre-2.0.0, no external consumers. Co-Authored-By: Claude Opus 5 (1M context) --- changelog.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.mdx b/changelog.mdx index 7b8cb5d..a396e2e 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -27,6 +27,15 @@ description: "Stay up to date with the latest agentsfleet product updates, new f - **The three isolation tiers sit on one row.** Two columns wrapped the third onto a row of its own. + + ## The free trial ends per account, not on a calendar date + + The trial boundary was a constant compiled into the server and both web surfaces. It passed at `2026-08-01T00:00:00Z` and flipped pricing for every tenant at once, with no deploy. The boundary now lives on each account — `billing.tenant_billing.free_trial_ends_at`, where `NULL` means open-ended — and every account today is open-ended: a trial ends when an end date is set on it, never on its own. + + - **`free_trial.ends_at_ms` on `GET /v1/tenants/me/billing` is now nullable.** Null means the account's trial has no end date set — it is not a missing value. Render it as "no end date", never as an expiry at the epoch. + - **The pricing pages no longer print an end date.** The banner and hero pill read "Free during early access", and the Terms point at the Dashboard for an account's own boundary instead of naming a date that can go stale. + + ## Every runner lease says whose workspace it belongs to