# Creator Bridge v2

> 当前强制规则：DSH 官方源码与构建产物只读。插件工作不允许 Host patch、修改临时官方副本或重建官方子项目。`update prepare/verify/apply/rollback` 已禁用，仅保留 `update plan`；后文历史版本说明不解除该规则。


Creator Mode+ is a user preset plus one DSH plugin. It brings ten fixed DSHX
operations into an ordinary DSH session without giving that session control of
its Host process. Stable DSHX `>=0.9.1 <0.10.0` supplies atomic single-Home Host
discovery/attachment, temporary-Home cold-boot verification, workspace-aware
scaffolding, source-preserving watched-plugin removal, external safe profile-bundle
removal, proactive integrity quarantine, the external Guardian, durable recovery state, the seven-surface
activation contract, and the read-only Harness version inventory and plugin-only source boundary.

## Roles

| Role | Authority |
|---|---|
| Creator Mode+ session | Claim one plugin, create files, check contracts, plan activation, perform bounded new-client activation/removal or server hot replacement, read status |
| External DSHX Guardian | Monitor the Host, journal activation, quarantine a culprit or missing claimed link, recover Host/official Loader failures, open a crash-loop fuse, persist incidents |
| User | Approve normal impactful activation and decide what to do after a fused or ambiguous incident |

The supervisor is outside DSH. It is not the model session and does not require
the user to watch every command. No model-facing tool accepts a shell string,
arbitrary argv/path/profile/port, or Host start/stop/restart operation.

The preset still inherits Standard's coding shell, but that shell is not the
external supervisor. RC8 and RC2 inject `DSH_SHELL=1` into every model shell
call; DSHX v0.7 rejects raw mutation/process commands at its CLI boundary. This
keeps an old or mistaken Creator session from bypassing the ten fixed tools with
`dshx start`, `restart`, `activate-new-client`, or profile shipping commands.
The only Harness-update exception is read-only `dshx update plan`; the mutating
update stages remain outside the Host.

## Fixed argv contract

The ten model-facing tools map to exactly these child CLI shapes:

| Tool | Allowed child argv |
|---|---|
| `dshx_status` | `status` |
| `dshx_browser_open` | `browser open --json` |
| `dshx_claim_plugin` | `creator claim <plugin-id>` |
| `dshx_request_takeover` | Host user question, then private-grant `creator takeover <plugin-id> --json` |
| `dshx_scaffold` | `creator scaffold <plugin-id> <declared-kind>` |
| `dshx_check` | `check <plugin-id>` |
| `dshx_activation_plan` | `activation-plan <plugin-id> --change <declared-branch>` |
| `dshx_activate_new_client` | `activate-new-client <plugin-id> --profile web --port <Host-derived-port>` |
| `dshx_remove_plugin` | `creator remove <plugin-id>` |
| `dshx_hot_reload` | `hot-reload <plugin-id> --profile web --port <Host-derived-port> --json` |

The approved eighth operation performs bounded official module HMR, not Host restart. The bridge supplies JSON output and trusted session/Host context, refreshes the claim first, and accepts no model-controlled path, profile, port, argv or shell. A successful module receipt remains pending functional verification; a failed attempt cannot reuse an earlier successful replacement receipt. The fixed tool accepts only root-scope receipts. Explicit preset-private replacement stays external and requires its own runtime acceptance, never a self-replacement tool or managed-shell bypass.

Multi-file server implementations declare exact package-relative `hotReload.artifacts` in `dshx.yml`. The receipt binds before/after hashes for that complete set and its exact watch roots. This matters because an entry-only reload can leave an imported helper cached. Creator+ declares its complete server file set in `dshx.yml`, excluding its browser client; a self-upgrade must replace those files together and prove that the existing session uses the new tools.

The bridge appends a fixed `--json` output flag to activation-plan (not model input). Its session-local delivery journal stores plan/check metadata and validated hot-replacement receipts under the selected Harness `.dshx/creator-plus/deliveries`; credentials and conversation content are excluded. Status and session recovery expose pending delivery across normal launcher restarts. A new Host does not mark the feature accepted, and old module proof is labeled historical when its PID no longer matches. Status uses Connection authentication for same-origin manifest and bundle proof; actual behavior remains a separate required check.

Session lifecycle may additionally call fixed internal watch, release, recovery
pull, and recovery acknowledgement argv. Tests must execute every row and every
internal lifecycle shape through the allowlist; registering a tool name does not
prove its child argv is reachable.

`dshx_remove_plugin` provides bounded source-preserving removal. Harness version inventory is read-only; source-changing update stages are disabled for every caller.

DSHX v0.7.4 makes App, direct CLI, and dshx launchers for one long-lived Web
Host per real `DSH_HOME`. `start` attaches to one existing Host, while duplicate
or unknown Host/Home evidence fails closed. `verify-boot` uses a temporary Home,
always tears it down, and rejects `--keep`. These remain external-supervisor
rules and do not grant process control to Creator.

DSHX v0.7.5 serializes same-Home start, restart, apply, and rollback across
Harness checkouts; binds PID, OS start time, Home, profile, and root; and
re-runs discovery after spawn. An affected or identity-unknown live Host blocks
installation-directory mutation.

`refusing an operation outside bridge v2` from one of these fixed tools means the
bridge contract itself is broken. The session reports the exact tool and error,
preserves the claim and source location, and stops. It must not reinterpret the
error as a supervisor decision, switch to raw shell or manual profile edits, move
the project, or report a later lifecycle stage as successful.

The scaffold command stamps the immutable session workspace from
`exec.agent.session.header.cwd`. If Harness `my-plugins/<id>` is outside that
writable workspace, DSHX creates the source below the workspace and creates the
Harness link atomically. The model supplies neither path, and the user is never
asked to add the link manually. For a fresh `new-client`, implementation, build,
and `dshx_check` follow scaffold before activation planning because the plan
validates the built lazy-CJS handoff. Other build-ready targets may plan as soon
as the target exists.

## Trusted identity and concurrent ownership

The bridge creates `DSHX_CREATOR_CONTEXT` from the tool execution object, never
from model input:

```text
exec.agent.id + callId + rootCallId
  + Host pid + Host parent pid + current Web port + bridge version
```

At `agent/created` (the session-start event; `agent/session-start` is gone), the bridge arms Guardian and pulls recovery incidents. The listener does not return that promise, so a recovery failure cannot reject serial session creation.
for that exact persisted session. Once a plugin id is known, the session calls
`dshx_claim_plugin`; every other named-plugin operation refreshes the claim.

- One session owns at most one plugin at a time.
- Different sessions can own different plugins concurrently without a fixed cap.
- One plugin cannot have two session owners.
- Build/check work remains concurrent. Only the watched live-activation section
  uses a global inter-process lock.
- Claim and incident registries use atomic locks and rename; `agent/disposed`
  releases the lease. A 24-hour expiry requires revalidation; it does not authorize another writer.

## Complete DSHX v0.7 preflight

The standalone package does not accept `0.7.x` by string alone. Before any fixed
operation or installer mutation it requires:

- package identity `dsh-external-plugin-devkit` and stable version
  `>=0.9.1 <0.10.0` (0.9.0 and 0.7.9 are rejected; 0.9.2 fits; the desk pin must be `dsh-v0.2.0-rc.2`, SHA `639ed015397290b3745d163aafe02ffee4aa3f84`);
- same-Home Web Host discovery/attach, three-state PID/port probes, and
  temporary-Home verification teardown;
- Creator claim/scaffold commands and Bridge v2 context validation;
- source-preserving watched-plugin removal, external safe profile-bundle
  removal, and proactive claimed-link integrity quarantine;
- external Guardian and official Loader-failure recovery implementation;
- check, activation-plan, and bounded new-client command surfaces;
- the managed-shell gate and the read-only Harness version inventory and plugin-only source boundary;
- Creator+, Guardian, live-activation, and Harness-update knowledge contracts.

Missing or prerelease surfaces fail closed. Release verification also probes the
actual DSHX CLI version and contract markers through `npm run verify:dshx`;
fabricated fixture tests are not the live-checkout gate.

## New-client transaction

### RC1 authenticated Host proof

The bridge obtains the current Host's startup URL from the public
`connection.authenticatedUrl()` API. It passes it only in the child process's
private `DSHX_WEB_STARTUP_URL` environment, never in model arguments, tool output,
session provenance or transaction journals. DSHX exchanges it for a cookie in
memory and binds every proof request to the selected loopback origin. Authenticated
activation and absence proofs use the same transport. HTTP 401/403 fails promptly
as `WEB_AUTH_REQUIRED`, rather than being overwritten by a polling timeout.

An authentication failure is an infrastructure blocker: preserve source and the
claim and repair the bridge. Keep Host authentication enabled. Do not ask the user
to paste credentials into chat. External launchers may supply the same private
environment input; DSHX does not discover credentials by scanning App logs.

Changing this already-loaded server bridge requires the server activation branch;
it does not imply that ordinary plugin creation requires Host restarts.

`dshx_activate_new_client({ name })` is the only bridge operation that mutates
live registration. Its sole model-controlled value is a lower-case kebab-case
plugin id.

```text
scaffold -> implement/build -> dshx check / SOURCE_BUILT
  -> activation-plan new-client exits 0
  -> add or confirm the official Web profile link
  -> prove package and lib/client.js resolution from that profile
  -> journal session/call/Host identity and the exact patch preimage
  -> insert or semantically retrigger one watched-patch row
  -> poll the current Host manifest and served client.js
  -> HOST_TREE_ACTIVE + CLIENT_MANIFEST_PRESENT
  -> observe RC2 client graph sync on the current page
  -> verify actual behavior; reload only if graph transport is unavailable
```

The order is invariant. A failed new row is rolled back by DSHX. A nonzero
result stops the branch; the session does not compensate with package
installation, manual profile edits, or a Host restart.

## Safe removal transaction

`dshx_remove_plugin({ name })` is the only whole-plugin teardown operation. Its
sole model-controlled value is the claimed lower-case kebab-case id.

```text
claim refresh
  -> remove a standalone watched insert row, or append one unique disabled override
  -> poll the same Host PID until its manifest no longer contains the id
  -> run official dsh plugin --profile web remove while the dependency exists
  -> prove profile dependency and node_modules entry are absent
  -> if RC8 left an orphan profile link, detach it only after target verification
  -> detach only a Harness my-plugins symlink
  -> preserve the source directory
  -> HOST_TREE_INACTIVE + PROFILE_DEPENDENCY_REMOVED (+ SOURCE_PRESERVED when observed)
```

If same-Host absence cannot be proved, the operation stops with its live row
quarantined and leaves the profile dependency, Harness link, and source intact.
If the official remover deleted the dependency but left `node_modules/<id>`, a
retry resumes from the durable quarantine without asking pnpm to remove an
already-absent dependency. It may report `detached-orphan-symlink` only when the
entry is a symlink whose resolved target is the claimed Harness/source path;
directories and outside targets fail closed without recursive cleanup.
Creator infrastructure ids cannot self-remove. The preset-scoped bash guard
blocks direct teardown of a claimed plugin root, its Harness link, and the active
DSH profile while permitting ordinary component/file cleanup inside the source.

## External profile-bundle removal handoff

`dshx_remove_plugin` stops when a package is a boot-captured bundle without a
bounded watched row. The Creator session reports that boundary and hands the
operation to the external supervisor:

```text
dshx plugin remove <package> --profile web --port <current-port>
  -> prove the same-name Loader row in current __DSH_BOOT__
  -> write or resume one exact disabled tombstone
  -> prove same-PID HOST_TREE_INACTIVE
  -> run the official profile remover
  -> prove dependency, bundle, and link absence
  -> retain the tombstone while the old boot is alive
  -> after a later normal App boot, rerun and remove it only with start-time proof
```

The command also resumes the dependency-gone/bundle-leftover failure seam. It
does not restart the Host, delete source, or grant process control to Creator.

## Guardian recovery

Guardian runs as a detached Node process outside the DSH Host. It evaluates Host
pid and loopback HTTP health and uses the same-port transaction journal for
attribution:

| Confidence | Evidence |
|---|---|
| `high` | An activation transaction is active when the Host fails |
| `probable` | The most recent unrecovered transaction finished within 15 seconds |
| `ambiguous` | No single short-window transaction can be named |

For high/probable attribution, Guardian restores an inserted row's exact
preimage or disables an existing row while retaining that preimage for a checked
retry. If another session has already changed the same patch, Guardian appends a
transaction-unique disabled override instead of overwriting the whole file with
an old snapshot; a retry removes only that marker. It never deletes plugin source.

```text
Host failed
  -> select active/recent same-port transaction
  -> quarantine the causal live row when attribution exists
  -> if another supervisor restored the port: do not open a duplicate listener
  -> otherwise restart the same Web target once
  -> a second failure inside 30 seconds opens the fuse
  -> persist incident
  -> steer incident to the owning session when it starts/resumes
  -> acknowledge delivery
```

An incident steering message interrupts normal work. The Agent inspects its
confidence, plugin, rollback and log excerpt, repairs preserved source, runs
`dshx_check`, and only then retries the original lifecycle branch.

Creator+ does not register or wrap Host SIGINT/SIGTERM handlers. Explicit DSHX
stop/restart disarms before signaling a DSHX-owned Host. An adopted Host records
its launcher pid; when that launcher exits, Guardian neither resurrects the child
nor leaves behind a Guardian replacement tied to that App lifetime. Manual DSHX
stop or restart refuses adopted official/App Hosts.

On every healthy cycle, Guardian also checks only claimed clients that are still
active in the watched patch. If such an id has lost its resolvable profile
package, Guardian removes the byte-identifiable standalone row or appends a
unique disabled override, waits for same-Host manifest absence, and records a
`plugin-integrity-failed` incident for the owning session. It does not delete
source, clean the profile dependency, stop, or restart the Host. This is an
independent fail-safe for an older Agent or script that bypassed the bridge and
prevents a later cold boot from consuming stale active configuration.

## Official client-Loader recovery

The package also contributes an immediate, self-contained browser client. It
listens to RC8 Loader status and the framework-free `Failed to load plugins` boot
page. It sends only bounded failed entry ids and error text to one same-origin
POST route. That Host route—not the browser or model—stamps Host pid, parent pid,
and port and invokes fixed `dshx creator client-failure` argv.

DSHX may quarantine only one exact candidate:

- an active same-port transaction whose plugin appears in the failed ids;
- one exact recent unrecovered transaction for a failed id; or
- one uniquely claimed failed id already present in the watched patch.

A stale Host identity, unknown id, or multiple candidates is ambiguous and
changes no plugin row. After quarantine, the bridge waits for the current Host
manifest to prove the id absent. Only then does the browser reload once. The
incident remains durable and is steered to its owning session. A failed report
gets one delayed retry to cover `agent/created`/Guardian arm races; the browser
fuse prevents an unbounded reload loop.

The POST route is a Host-scoped leased resource, not a generation-scoped side
effect. RC8 may keep an older session generation alive while mounting a newer
one after the preset composition stamp changes. Independently loaded bridge
generations therefore share one route broker keyed by the WebServer instance;
the newest live generation handles requests, disposal falls back to another live
generation, and only the last lease unregisters the route. The installer also
preserves the exact composition-file stamp when its bytes are unchanged so
metadata-only upgrades do not manufacture a new generation.

## Harness version inventory boundary

Only `update plan` is available. It inventories versions, dirty state and plugins without proving a build or runtime behavior. DSHX rejects `prepare`, `verify`, `apply` and `rollback` with `CORE_SOURCE_IMMUTABLE` for every caller. The external supervisor has no exception. A plugin requiring a new Host API must report that capability gap or use another public extension point.

## Compatibility and evidence boundary

Supported: the official DSH browser WebUI, public Cordis plugin forms, public
client runtime, and public UI slots across the RC8 Creator/Guardian contract and
the RC2 package/update line and the authenticated Web line through `dsh-v0.2.0-rc.2` (SHA `639ed015397290b3745d163aafe02ffee4aa3f84`). The plugin peer range is `>=0.2.0-rc.1 <0.2.1`. It accepts `0.2.0-rc.2` and stable `0.2.0`, rejects `0.2.0` alphas, and rejects `0.1.7-rc.2`. User presets are profile includes of an `@deepseek-ai/dsh-agent-preset` declaration derived from the shipped Standard patch; `$DSH_HOME/.agent-presets` is not read.

Outside acceptance: native menus, window chrome, App IPC, desktop bridges, and
shell-specific refresh behavior. A wrapper may work when it embeds the same
WebUI unchanged, but browser-WebUI reproduction is the defect gate.

Guardian proves Host process/HTTP recovery and the narrow official Loader-failure
recovery above. A component render exception, loaded package id, visual
correctness, and functional behavior remain separate evidence. These layers are
independent: `SOURCE_BUILT`, `ARTIFACT_SYNCED`, `NEXT_BOOT_REGISTERED`,
`PRESET_ROSTER_VISIBLE`, `PRESET_SESSION_ACTIVE`, `HOST_TREE_ACTIVE`,
`CLIENT_MANIFEST_PRESENT`, `CLIENT_LOADED`, and `VISUAL_BEHAVIOR_VERIFIED`.

Changes to safe removal, the bash guard, Connection authentication or preflight
are server changes and need live activation evidence. They are not automatically
restart-required. A checked server plan returns `HOT_RELOAD_READY` with a fixed `nextAction`.
Unknown or failed target evidence remains `ACTIVATION_DECISION_REQUIRED`; a launcher handoff supplies identity, not approval.
Official HMR of a root Loader entry does not prove replacement of a preset-private
bridge. Keep that scope distinction explicit and verify the actual fixed-tool
behavior before claiming delivery. Managed upgrade preserves an unchanged
`agent.cordis.yml` stamp: skill/metadata refresh alone neither creates a generation
nor justifies an immediate restart. The approved eighth tool must traverse the
same allowlist and provenance gates as the existing operations before release.

## Private browser access

RC1 local Web authentication is independent of provider/account login. During
watch/claim, the bridge uses the official Connection startup URL to refresh an
owner-only, expiring DSHX handoff bound to Home, checkout, PID, process start and
port. The URL stays in private subprocess input; assembled stdout/stderr is
redacted. An older Connection without authenticatedUrl remains supported and
must still pass the actual unauthenticated Web proof.

Read `dshx kb cat contracts/browser-access` before browser testing. The managed
shell may run read-only `dshx browser status`. Use the no-argument fixed
`dshx_browser_open` to open this session's externally approved browser adapter.
Adapter configuration and raw bind/open commands remain external-supervisor work. A missing credential is `WEB_AUTH_REQUIRED`;
an unavailable permitted browser adapter is `BROWSER_ADAPTER_REQUIRED`. Do not
restart the Host, open a second Host/port, request account login, or switch to
another agent's browser to resolve either status. The external adapter uses its
own permitted browser context and receives private JSON on stdin. Browser
access does not prove the plugin feature works.

This works with official CLI, App, and DSHX launchers. Without Creator or a
DSHX-owned launcher, the user/launcher must privately bind the official startup
URL once per Host lifetime. Never infer credentials from an open port or request
a token in a conversation. Expired or changed-Host handoffs need refresh.


## Installation routing and candidate scope

Creator can install supported Web plugins through the fixed new-client operation;
the managed shell does not need a `dsh` executable. Existing-plugin branch trials
follow the bundled `existing-plugin-trials.md`: candidate preparation is separate
from promotion to the claimed target. No arbitrary source-retargeting operation
is added. Explicitly preserving the installed directory requires a scoped
external handoff, not an inferred Host restart.

Delivery output names the exact `sourcePath` and limits its evidence to that
path. `SOURCE_BUILD_REQUIRED` requests a fixed check of that target; undecided
server plans point to bounded hot reload only when unrelated plan gates passed.
Host mismatches and failed gates cannot receive runtime-verification guidance.


The ninth tool is session-bound browser opening, not process control. It requires
`session-browser-open`: external setup pins a reviewed self-contained executable
snapshot using `dshx browser configure <session-id> <absolute-adapter-path>`.
The no-argument tool selects only that session's snapshot, supplies authentication
privately, and returns whitelisted browser status. Raw managed-shell browser
configure/bind/open remains denied. Setup never opens a browser; only the later
fixed call does. A changed adapter requires external review and reconfiguration.


## Delivery continuation (0.3.7)

Fixed results lead with `outcome`: status, scope and `continueWith` actions.
A checked server plan produces `delivery.nextAction` for `dshx_hot_reload`.
For DSHX 0.7.6, only the exact evidence-only server plan is adapted to bridge
exit code 0, retaining its original `commandExitCode: 1`; unrelated errors remain
blocking. DSHX 0.7.7 returns a successful plan directly and grants no activation
or restart proof merely by planning.

Browser adapter failure retains the server delivery state and permitted next
action. Current-Host authentication errors still block dependent live proof.
An already-authenticated, task-authorized UI or a plugin command/service can
supply feature evidence without configuring this optional browser adapter.

The sealed executor code is a development integration, enabled only by an
explicit `developmentExecution: true` composition. The ordinary preset keeps
the established ten fixed tools and native approval/guard stack. Enabling the
experimental path retains its strict executor/provenance requirements; absence
of that optional service is not a default-mode prerequisite.

## 用户确认后接管

插件已被别的对话认领时，调用 `dshx_request_takeover({name})`。当前对话会展示原对话的实际标题、会话 ID、工作区、认领刷新时间和运行状态。用户选择“接管到当前对话”或“停止旧任务并接管”后，固定 bridge 才会暂停旧对话及其子任务的工具权限，停止并等待其后台命令和终端结束，再由 DSHX 原子转移认领。默认选择“取消”。无需找回旧对话，也无需等待 24 小时。

确认走官方 `userQuestions` UI，独立于 `approval/request`。Approve for me 的自动允许、模型传入的布尔值和自由文本“已批准”都不能替代选项确认。确认绑定原认领快照，五分钟后失效；提交凭据只在 Host 闭包和固定 CLI 环境中传递，一次使用、有效期一分钟。原认领刷新、另一次接管或 Host 身份变化都会使旧确认失效。

旧对话及已存在子任务的撤销记录独立于租约保存，所有普通工具调用都被拦截，保留 `dshx_status` 与重新申请接管的入口。该保护属于 Host 生命周期，跨 preset 卸载、HMR 和认领释放继续生效；不会修改会话日志锁。后台任务依照官方 jobs/terminals 的完成与资源释放约定等待，不能把“取消已请求”当成“已经停止”。

正在激活、持有者状态无法核实、停止失败、确认取消或超时，都不会授予新会话权限。已开始的停止操作不会被自动恢复。可用外部 `dshx creator inspect <plugin> --json` 查看原认领及待处理交接；不要手删 claims 或 session.lock。`creator takeover` 是固定桥内部提交协议，缺少一次性凭据会拒绝，不能通过 `--force` 调用。

租约到期只表示认领需要重新核验，不再自动授权第二个写入者。正常 `agent/disposed` 仍释放认领；移交中的 dispose 不得破坏正在比较的原认领。


## Official Desktop profile support (local compatibility update)

The fixed bridge derives `desktop`, its port, Home, and runtime root from the public `profileContext`; none becomes model input. The CLI preserves Web behavior. For Desktop, a per-invocation private capability returns only config entry identities, or authorizes one install/remove for the current claimed plain plugin. The owning Host calls the public `@deepseek-ai/dsh-plugin-manager/operations` `runPluginCommand` with its bundled package manager and official profile lock. New bundle activation is disabled; the existing checked watched-patch transaction still owns activation and removal. Capabilities expire, are revoked at operation completion and generation disposal, and are never returned in tool text.

Guardian validates the Electron child identity and monitors the Desktop Host. It may quarantine an attributed plugin failure, but never stops, replaces, or restarts the Desktop Host. Electron owns that recovery and normal quit. Desktop HMR binds the discovered application root independently of the plugin-development checkout. Package imports, checked artifacts, claims, same-PID proof, and feature acceptance remain required.
