Profile templates and the default, optional, on-demand, retired, and
installation-owned bundle lists move to the new data-only package
@deepseek-ai/dsh-official-bundles, so editing a bundle list no longer
touches app-boot.
The packer images the web template bundles, every optional bundle, and an installation manifest instead of a dumped composition, and the Worker boots that profile through app-boot like dsh web. Package-local lazy client chunks move into content-addressed archives that the VFS fetches on first asynchronous read; client-modules reads chunks asynchronously.
The Worker replaces node-addon-require-builtin with Node v24.18.0 internal-module interfaces and reports Node 24, so plugin metadata, the Cordis Loader, and HMR reach one cascaded loader backed by the Worker loader. Resolution failures carry Node error codes, the empty load cache lets HMR apply profile changes, and every optional bundle switches on and off live. Platform stubs throw ERR_FEATURE_UNAVAILABLE_ON_PLATFORM.
Delete @deepseek-ai/dsh-invariants, every package's ./invariant companion
and its tests, the invariant gates and Vitest setup, the scoped-event
resolver generator, and the INVARIANT-coded listener rethrow paths.
Update docs, READMEs, Agent Notes, and add an upgrade guide.
* feat(preset): declare Agent compositions in profile YAML
* fix(preset): share scope binding cleanup and refresh module graph
* fix(preset): use host syntax colors in the YAML editor
* fix(preset): write new profile declarations as block YAML
* fix(preset): align eager activation with browser and worker surfaces
* fix(ui-agent-preset): retain the existing preset card layout
* fix(preset): keep rows waiting for a Host service mounted and re-audit after settlement
A preset row whose Host provider was still activating at declaration time
was reported as waiting for a missing service, and the registry recorded the
definition as broken for the rest of the process. Split the mount audit into
failed and pending rows: failures and root-realm leaks still reject the
mount, while pending rows stay mounted and every read and binding re-audits
them after the Host Loader tree settles.
Remove the accidental self-dependency of @deepseek-ai/dsh-web-app and its
lockfile self-link. Archive the copy-only preset authoring note, which the
declarative-preset note fully supersedes, and update the ralph note's
restore recipe to the profile-patch mechanism.
* chore(lint): re-key and prune the unknown-cast baseline after the master merge
* refactor(web-app): ship each Agent preset as its own bundle patch file
`dsh.bundle.patch` accepts an ordered file list, so the four shipped preset
declarations move out of the 1000-line web patch into
`presets/<id>.patch.yml`, one insert per file, applied after the host patch.
The host patch keeps the preset registry row. Gates and test scaffolds that
read the web layer resolve every patch file through `bundlePatchPaths`
instead of one hardcoded path.
* refactor(preset): drop the save notice injected into live Agents
The notice duplicated the save result the Web editor already shows, and
after the producer-owned message sources it would have needed its own
persisted source kind. Saving now only persists and reports the activation
diagnostic; the persistence catalog is unchanged from master.
* docs: regenerate the module graph after dropping the registry's llm dependency
* test(ui-agent-preset): cover the guide dialog's keyboard handling on the declarative section
* fix(preset): address the remaining review comments
Apply the lowercase id rule only when creating a declaration, so presets
declared with other ids stay editable. Export `isBuiltInPreset` from the
display fold and key the client card groups on it. Remove the dead `error`
and `retry` locale keys, the JSDoc orphaned by the `trust` removal, the
`trust` fields in the plugin-inventory test fixtures, and the stale
`dsh-agent-presets` package name in comments and READMEs.
* refactor(preset): make the Web preset page view-and-select only
Remove the child-plugin YAML editor, the `agent_preset` tool and the
registry's read/save Remote methods. Presets are declared and changed only by
bundle patches; the settings page keeps the roster, the new-task default and
the mode help, and its question icon explains that and offers to start a
Creator-mode task. The `editing-cordis-compositions` skill and the Creator
persona describe the bundle-based path, and the authored skill-load Session
and Web snapshots are refreshed for it.
* docs(skill): make the composition skill self-sufficient for preset authoring
State where the shipped declarations live, list every declaration field,
inline a complete minimal bundle and an override example, and name the
verification calls, so Creator mode no longer reads DSH package sources to
infer the format. Refresh the authored skill-load Session for the new text.
* test(tools): drop the removed agent_preset tool from the catalog expectation
A readable V3 child may have no own descriptor, an unknown descriptor version,
or multiple descriptors. Those states do not provide a unique discovery fact,
but they do not make the parent or the retained child history unreadable.
Rejecting the entire parent prevented otherwise valid V3 Sessions from opening.
Append a missing parent catalog row only for exactly one supported own child
descriptor. Keep existing parent entries and every child record when no fact is
available. Retain rejection of mismatched creation times, unambiguous mode/label
conflicts, malformed known fields, unreadable membership and revision drift.
Cover raw and compressed read/write publication, preserved source bytes, late
descriptor availability, inherited descriptors and Preview packing. Document
that unavailable discovery evidence can leave a child absent from its parent
catalog and does not trigger automatic backfill after the V4 successor exists.
Extracts the child-evidence behavior from 7ba7e174dd1 and the Preview regression
from 9c85eb60bd25, preserving the original migration authors' work while keeping
message representation and extension interpretation outside this commit.
Co-authored-by: Dudu-0223 <[email protected]>
Merge 3ea52fc3e475a3e7c430812bde4209258416e57b into a0a61a8237f61344a01448a97954df603d8fff73. Retain the V2-to-V3 migration dependency alongside native system flock support, removing the replaced fs-ext dependency. Union the lockfile workspace importer entries; frozen installation validates the result without regeneration.
Preserve release publint async lane-signal cancellation, close ownership, and spawn-error regressions, satisfying the incoming CI budget intent. Keep canonical, prompt, preset, and latest migration regression behavior. Rename an arbitrary preset fixture value to custom-agent to avoid the inherited vendor-rescope false positive without changing test semantics.
Validation: frozen install; full build including Darwin addon; focused V3/persistence/prompt/publint and runtime tests; built migration, two-process lease, and loader smokes; native flock and package-matrix tests; touched dependency and CI owner tests; all hygiene leaves (vendor residue repaired and rechecked); doc-sync 34/34.
Both coverage lanes now run before any build, so the post-build
uninstrumented gate wording applies only to the serial-windows complete
reference; preview builds still exercise the suite against real
artifacts.
A settled top-level `read_image` call printed its raw attachment object as
literal text in the tool card — `{"type":"image","attachment":{…}}` —
instead of the image, because no presentation metadata told a client card
how to present the reference and the tool-card layer had no image concept.
Host: `read_image` declares an `output.presentationMeta` persisting
`{ path }` only. The attachment reference deliberately lives in the
settled result content — the single record a `tools/post-execute`
replacement rewrites — not in `meta`; the id is opaque and
provider-owned, checked for existence only.
Client: `imageCardModel` derives the card from the call head, the meta
path, the result's own image block, and a shape-matched envelope. ToolRow
gains an `image` card slot; the `read_image` toolview declares the
Tool-owned `tool.call.images` slot as its child and dispatches the
gallery through it. ui-chat down-threads the session-authorized loader
(`ChatNodeOwnerProps.loadImage`), so the tool layer supplies only derived
references plus the loader and never imports an attachment
implementation; ui-attachment fills the slot with its message gallery
renderer. The card keeps the envelope text below the gallery for the
no-attachment-plugin deployment. An image-bearing tool registers a keyed
toolview; the generic fallback keeps its flattened text. `read_image`
joins the read variant with its own locale title key; both rows share
`read-family-row.tsx`.
Verification: `read-image.spec.ts` (metadata projection, envelope by
shape, reference narrowing, real-execution round trip, rejection
branches incl. non-digest ids), `image-card.client.spec.tsx` (derivation,
row render site dispatching the slot, keyed registration with the
child-slot declaration, empty-slot fallbacks, media-type enum), keyless
snapshots (`read-image-gif` added; read-image/-dimension/-reencode
updated to the `{path}` meta), five injected-defect negative controls,
and a demo GIF recorded from this PR's head through the official
image-capable model.
Two private experimental packages run the whole harness tree inside one
dedicated Web Worker. dsh-experimental-webworker-runtime owns the in-memory
VFS (BigInt stats with per-path identity and strictly increasing mtimes),
the CommonJS wrapper loader over a lazily-evaluated builtin table whose
shims typecheck against Node's own module types, the postMessage tunnel
speaking plain HTTP, the AsyncLocalStorage runtime, and the worker
assembly. dsh-experimental-webworker-packer lowers every module body at
pack time against the shared wrapper contract, sweeps the profile closure
by static reachability, and writes a deterministically gzip-compressed tar
the worker inflates through the browser's native DecompressionStream while
it downloads.