Merge branch 'stack/agent-profiles-1-seam' into stack/agent-profiles-3-wire

Rewires this layer onto the standing-mount model:

- serviceForAgent roots its search at the agent's standing mount (parent
  scope key → live mount fiber) — the composition no longer lives under the
  agent's own fiber, and two agents on one preset now address ONE instance,
  which the sharing test asserts instead of distinctness.
- viewFor/historyPage take a registry view SCOPE. A live agent is that scope;
  a cold read uses the recorded preset's standing key via standingKeyFor —
  composing plugins but starting no agent, session, or turn. A header without
  a preset (a pre-roster log) renders through the DEFAULT preset's standing
  layer; an unusable preset degrades the read to generic cards, never fails
  it. This turns produced-files and chat-scroll green structurally, with the
  token counts untouched (no resume, so the projections fold stays detached).
- The detached projections baseline now includes every standing unit's key at
  its empty fold (todos: null): the standing mount registers units
  deterministically, which is what makes the client's "omitted key =
  capability absence → clear" rule safe again. seeded-history's contract test
  asserts the new shape.
- The standard preset's realm preamble no longer claims a shared label pools
  instances — provide() throws on the second registration under one realm
  symbol; labels join REALMS.
This commit is contained in:
Yichen Jiang
2026-08-08 18:41:07 +08:00
24 changed files with 566 additions and 117 deletions

View File

@@ -1,18 +1,21 @@
# The `standard` agent preset: the full coding agent, mounted per session.
# The `standard` agent preset: the full coding agent, mounted once per process.
#
# This file is an AGENT-PLANE composition. It is mounted under one agent's
# scope context, so every tool and prompt section it registers belongs to that
# session alone. The host composition (`base.cordis.yml` + `web.cordis.yml`)
# keeps everything a preset must not own: the registries themselves, the
# sandbox and approval stack, persistence, and the model route.
# This file is an AGENT-PLANE composition. The roster mounts it ONCE under a
# standing scope; every session naming it joins by scope parentage, so the
# tools and prompt sections registered here cover each joined agent while a
# session's own state stays keyed per Session/Agent inside the plugins. The
# host composition (`base.cordis.yml` + `web.cordis.yml`) keeps everything a
# preset must not own: the registries themselves, the sandbox and approval
# stack, persistence, and the model route.
#
# A service row here MUST sit inside a group carrying an `isolate` realm.
# Without one it publishes into the root realm, where it is process-global
# rather than per-session and the second session mounting this preset collides
# with the first; `dsh-agent-presets` rejects that at mount. `true` means an
# entry-local realm — one private instance per mounted session, which is the
# default this deployment wants. A shared label would instead pool one instance
# across every session naming it.
# Without one it publishes into the root realm, where it is process-global
# another preset publishing the same name collides, and a host reader would
# resolve one preset's instance for every session; `dsh-agent-presets` rejects
# that at mount. `true` means an entry-local realm: this standing mount's own
# private instance, apart from every other preset's. (A shared label does NOT
# pool instances — `provide()` throws on the second registration under the
# same realm symbol; labels join REALMS, and are not what this file needs.)
# ── identity ────────────────────────────────────────────────────────────────