qwen-code/docs/developers
jinye 4338120100
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 1/2 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 2/2 (push) Waiting to run
E2E Tests / channel-plugin E2E (nightly) (push) Waiting to run
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (push) Waiting to run
SDK Java / ubuntu-latest / Java 11 (push) Waiting to run
SDK Java / ubuntu-latest / Java 17 (push) Waiting to run
SDK Java / macos-latest / Java 21 (push) Waiting to run
SDK Java / ubuntu-latest / Java 21 (push) Waiting to run
SDK Java / windows-latest / Java 21 (push) Waiting to run
SDK Java / Real daemon E2E / Java 11 (push) Waiting to run
feat(serve): resolve and report the daemon memory budget (#8245)
* feat(serve): resolve and report the daemon memory budget

The daemon has no notion of how much memory it has. It samples its own
RSS and heap every five seconds, and polls the primary ACP child's RSS,
but there is no limit anywhere to divide those by: no cgroup read, no
heap-size limit, no ratio, no `limits.*` memory field. Every number it
reports is an absolute byte count with nothing to compare against, so
"how close to exhaustion is this daemon" cannot be answered from
`/daemon/status` at all.

Resolve one set of figures at boot and report them. Configured and
effective budgets are separate: the effective value is capped at resolved
cgroup or host memory, so an operator passing a budget larger than the
machine gets a denominator the machine can actually back, with the
discrepancy visible rather than silently resolved. A derived budget below
the documented minimum is reported as `insufficientMemory` rather than
clamped upward, which would have invented capacity that does not exist —
a 768 MB host would otherwise report a 1 GB budget and poison every ratio
computed from it.

`limits.memory` carries the static figures, including `legacyCeilingMb`:
the ceiling an ACP child receives today with no budget involved, so the
gap between current behavior and any future policy is measurable before
that policy exists. `runtime.memory` carries live counts and the advisory
per-child share at both the registered and the live child count.

Nothing here sizes a child. Dividing the pool by a workspace count is not
a sound policy on its own, and the advisory shares exist to show why: on
a 32 GB host with 25 registered workspaces and only the preheated primary
live, a registered-count divisor would cut that child from 16384 MB to
614 MB for memory no dormant workspace is holding, while the per-child
floor still lets 25 children authorise more than the pool. Registration
is not allocation; a real policy needs admission at spawn time keyed on
concurrently live children, and it needs this data to be designed
against.

Applying such a share is also a compatibility change even with no
refusals, since it alters child GC and OOM behavior — so it is not
something this change should slip in under the heading of reporting.

Refs #8182
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(serve): report honest memory counts and guard the registered share (#8245)

* fix(serve): reuse workspace snapshots when counting active children

Counting active ACP children from `listManaged()` is right — `list()` only
returns entries in `active` state, so a workspace mid-drain, mid-replacement,
or blocked still holds a live child that `list()` drops. But taking the count
by calling `getDaemonStatusSnapshot()` again per managed runtime undoes the
existing reuse of the primary bridge's snapshot, and `getDaemonStatusSnapshot`
rebuilds the whole session array on every call.

The second pass also reads the tree at a different instant than the rest of
the response, so `activeAcpChildren` could disagree with the session and
channel figures beside it.

Reuse the snapshots already taken instead, keyed by bridge, and fall back to a
fresh call only for a managed runtime the first pass missed — which is exactly
the non-`active` entry the `listManaged()` change exists to catch.

The reuse this restores was already guarded by a test asserting one snapshot
call per bridge, but that test resolves no memory budget, and the second pass
ran only on the budget path — so it stayed green while every production
`/daemon/status` call did the work twice. Added a case that resolves a budget
and asserts the same property; it fails against the previous commit with
"expected 1 times, but got 2 times".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(serve): address review feedback on daemon memory budget (#8245)

* fix(serve): import isValidMemoryBudgetMb in serve command (#8245)

* fix(serve): address review feedback on daemon memory budget (#8245)

* fix(serve): stub isChannelLive on serve test fake bridges (#8245)

* fix(serve): address review feedback on daemon memory budget (#8245)

- Make the stderr-gate test host-independent by pinning os.totalmem
  through a vi.mock toggle instead of reading the runner's cgroup
- Add a spawn-path constant parity test enforcing that
  getAcpMemoryArgs and legacyChildCeilingMb agree on the fraction
  and cap, converting the comment-only invariant into a test
- Narrow the mirror comment to name only the two constants that
  actually have spawn-path counterparts
- Accept availableMemorySource through the resolveDaemonMemoryBudget
  seam so the constrained path is testable end-to-end
- Report maxChildHeapMb alongside minChildHeapMb on the wire so
  clients can distinguish the 16 GB cap from a large host
- Move the listManaged/list comment to the computation it describes
- Add a cross-reference at the opts literal for the late-assigned
  daemonMemoryBudget field

* fix(serve): address review feedback on daemon memory budget (#8245)

* fix(serve): address review — split fraction constant, sharpen parity test, deduplicate error, populate bootstrap memory (#8245)

* fix(serve): address review — document maxChildHeapMb, make parity test order-independent (#8245)

* fix(serve): address review — split parity test into two files to avoid cold re-import timeout (#8245)

* fix(serve): address review — correct session count, compatibility scope, bootstrap memory docs (#8245)

* fix(serve): address review — align help text framing, document default cap, fix stale comment (#8245)

* fix(serve): address review — add positive memory-budget validation test, correct activeAcpChildren docs (#8245)

* fix(serve): address review — document childRssBytes stale tail after watcher detach (#8245)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: Qwen Autofix <qwen-autofix@users.noreply.github.com>
Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-08-02 04:19:31 +00:00
..
daemon feat(serve): resolve and report the daemon memory budget (#8245) 2026-08-02 04:19:31 +00:00
daemon-client-adapters docs(serve): Close multi-workspace hardening gaps (#7019) 2026-07-16 17:33:53 +00:00
daemon-ui feat(web-shell): Add sidebar customization API for branding, navigation, session actions, and footer (#7379) 2026-07-21 11:20:51 +00:00
development feat(core): add GenAI time-to-first-chunk tracing (#8150) 2026-07-31 13:46:46 +00:00
examples docs(serve): Close multi-workspace hardening gaps (#7019) 2026-07-16 17:33:53 +00:00
tools feat(core): add project-level fork profiles (#8148) 2026-08-01 02:20:51 +00:00
_meta.ts docs(daemon): Refresh daemon docs in English (#5144) 2026-06-15 22:38:01 +08:00
architecture.md docs: refresh architecture overview (#8325) 2026-08-02 02:45:00 +00:00
channel-plugins.md docs(channels): Document loops and proactive delivery (#7628) 2026-07-26 07:32:18 +00:00
contributing.md revert: remove local PR verification gate (#7031) 2026-07-16 11:24:38 +00:00
qwen-serve-protocol.md feat(serve): resolve and report the daemon memory budget (#8245) 2026-08-02 04:19:31 +00:00
roadmap.md docs: standardize GitHub Actions capitalization (#6367) 2026-07-06 06:55:07 +00:00
sdk-java.md feat(sdk-java): Add daemon transport (#7463) 2026-07-23 12:38:34 +00:00
sdk-python.md doc[sdk-python] Expand Python SDK usage documentation (#3995) 2026-05-12 15:27:00 +08:00
sdk-typescript.md feat(web-shell): show subagent sessions in detail panel (#7380) 2026-07-22 02:31:08 +00:00