Merge branch 'stack/agent-profiles-3-wire' into stack/agent-profiles-5-web-ui
recompose becomes a parent re-link: the new preset's standing mount is ensured BEFORE the link moves, so a failed switch leaves the agent exactly as it was — the unmount-then-restore dance (and unmountPresetFor with it) is gone, and the restore-failure test now asserts the agent KEEPS its tools with the source directory deleted, because the standing mount is not the file.
This commit is contained in:
@@ -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 ────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -236,14 +236,13 @@ describe('web e2e: seeded history renders through cold resume', () => {
|
||||
// The seed carries a session/title event: the title unit is host-plane, so
|
||||
// it folds the detached log and serves the value with nothing composed.
|
||||
expect(typeof projections?.values.title).toBe('string')
|
||||
// `todos` is NOT here, and that is the contract rather than a gap. Its unit
|
||||
// is registered by `tool-todo` inside an agent's preset, so a detached
|
||||
// session yields it from exactly one place: a durable checkpoint written
|
||||
// while the session was live. This seed was written straight to persistence
|
||||
// and never ran, so it recorded none — and the answer no longer depends on
|
||||
// whether some UNRELATED session happens to be composed right now, which is
|
||||
// the whole reason the checkpoint row carries its own view.
|
||||
expect(projections?.values).not.toHaveProperty('todos')
|
||||
// `todos` IS here, as its empty fold (null). Its unit is registered by
|
||||
// `tool-todo` inside the default preset's STANDING mount, which the read
|
||||
// itself ensures — deterministically, not because some unrelated session
|
||||
// happens to be composed. A present-but-null key is what keeps the
|
||||
// client's "omitted key = capability absent → clear the row" rule from
|
||||
// wiping preset-owned projections on cold reads.
|
||||
expect(projections?.values).toHaveProperty('todos', null)
|
||||
})
|
||||
|
||||
it.skipIf(MODE === 'record')('lists the seeded session cold and renders its history from the log', async () => {
|
||||
|
||||
Reference in New Issue
Block a user