integrations/dsh-plugin
Q00/ouroboros通过 DSH MCP 客户端挂载 Ouroboros 的纯配置包,在 DSH 中提供 36 个涵盖需求访谈、Seed、执行、评估与演化流程的工具。
dsh-loopx-plugin is one independently versioned DSH package with three separate Loader rows:
packaged workflow skills into $DSH_AGENTS_HOME/skills (default ~/.agents/skills), and verifies the DSH-native loopx entry before DSH finishes loading it. /loopx-init remains the explicit repair command.
Session successfully invokes the exact loopx skill. It then asks LoopX whether another turn may run and queues the authoritative heartbeat task into that live DSH Agent.
/api/loopx.goalbar route required by DSH 0.1.5. Its web Client adds a compact GoalBar between DSH's native GoalBar and Queue dock rows, visible only for one exact live (goalId, loopxAgentId) binding.
Installing the plugin and starting DSH load and prepare these capabilities; neither creates a binding nor activates the Driver. The GoalBar does one bounded read when a browser row mounts, then watches exact-Session step/end and turn/end boundaries. It rereads LoopX only when the opaque revision of the authoritative binding or active Goal state changes; a watch lease also detects changes written outside that Session. DSH Agent-status events update an existing row without a LoopX business read. Until one exact Session contains valid typed loopx invocation evidence, its Driver makes no LoopX CLI, binding, quota, or heartbeat call, creates no timer, and queues no followup.
The package does not expose LoopX model tools, a binding sidecar, or its own Goal/Todo state. Models use the installed LoopX skills and call the LoopX CLI directly. LoopX remains the only authority for Goal, Agent, Todo, quota, activation, and durable thread-binding data. The GoalBar protocol and its deferred atomicity limit are specified in the versioned DSH native LoopX design.
Requirements are stable Node.js 22.22.3+ (excluding Node.js 23), pnpm, Python 3.11+ with pip, and network access for the first DSH start when no compatible LoopX CLI is already installed. LoopX itself is deliberately not a prerequisite. The initializer honors an explicit PYTHON_BIN; otherwise it tries python3, then discovers python3. executables on the supplied PATH in descending numeric order, then tries the bare name python. The last name is what a python.org Windows install registers, so it keeps that host reachable when python3 is absent or is the WindowsApps App Execution Alias that never starts Python. Unlike the versioned names it is not a PATH scan result; it is resolved when the candidate runs. Installation still checks the Python version and pip; reopening the managed runtime uses the same discovery and validates the LoopX CLI. No hard-coded minor-version list is maintained. When selecting Python for installation, an invalid explicit interpreter fails instead of falling back. Managed-runtime readback keeps the existing CLI fallback behavior. If the plugin must install or upgrade LoopX, it writes an isolated copy under $DSH_AGENTS_HOME/runtime/dsh-loopx-plugin (default ~/.agents/runtime/dsh-loopx-plugin) and never mutates the system Python environment. This works with externally managed Python distributions that enforce PEP 668; the plugin does not use --break-system-packages. This version requires LoopX 1.2.4 or newer, the published release that includes the Windows peer-file fix. Bootstrap, Driver and GoalBar use the same version floor; an older global or managed CLI is upgraded or rejected before business commands run. An explicit outdated LOOPX_BIN must be upgraded by its owner. Older plugin releases retain their original CLI requirements. Install the prebuilt release into the web profile:
dsh plugin --profile web add \
"https://github.com/loopx-project/loopx/releases/download/dsh-loopx-plugin-v0.1.1-beta.6/dsh-loopx-plugin-0.1.1-beta.6.tgz"The beta.6 package targets the qualified DSH 0.2.0-rc.2 API and retains the qualified frozen 0.1.5 and 0.1.7-rc.2 compatibility ranges. The exported legacy RPC registration remains available to explicit callers, but plugin startup always uses the shared API.
The source candidate additionally qualifies DSH 0.2.1-rc.2. Its frozen source host uses MCP client 2.3.0 and SDK 1.32.0 to address GHSA-6prh-2h8m-c8cw. These dependency overrides do not patch an independently installed DSH binary; that host's owner must update its affected MCP dependencies separately.
For a compatible DSH source build, use:
cd packages/dsh-loopx-plugin
./install.shStart DSH on loopback (port 0 asks the OS for a free port) and open the printed URL. The plugin finishes its idempotent LoopX CLI and skill bootstrap before DSH publishes the Web URL through its native Loader readiness boundary. The source candidate gates only LoopX's Host and Driver on loopxBootstrap, so disabling or uninstalling it keeps the shared Web server and runtime alive. The published beta.6 limitation is described under automatic initialization:
dsh --profile web --port 0Use /loopx immediately. If automatic initialization reports a safe failure in the DSH log, fix the named Python or package-manager problem and run /loopx-init once to retry; normal installation does not require that command.
Installation is the GoalBar opt-in: there is no separate remote endpoint or per-session grant. A row remains hidden until the exact DSH Session has one unique LoopX binding. After invoking the installed loopx skill for that Session, run the minimum authority readback inside that Session's DSH shell (or replace $DSH_SESSION_ID with the exact Session id):
loopx --registry .loopx/registry.json --format json \
resolve-agent-thread \
--host-surface deepseek-harness-native \
--thread-id "$DSH_SESSION_ID"status=bound with one exact pair admits the row; missing or ambiguous results fail closed and render nothing. Start resumes a stopped Goal and asks the Driver to evaluate only when that exact live Session already contains typed loopx skill activation evidence. It never activates an inactive Session. Pause stops the Goal and retires only future queued/scheduled continuation; it does not abort a claimed or running turn.
To start DSH from a terminal with this machine's stored LoopX provider credential without placing the value in argv, shell history, or output:
loopx dsh-launch webThe launcher uses DSH_HOME when set, otherwise ~/.local/state/loopx/dsh-home. Ordinary DSH installation defaults to ~/.dsh; launching the isolated home does not reuse that home's installed plugins. To reuse an ordinary installation, select its actual home explicitly:
loopx dsh-launch --dsh-home "${DSH_HOME:-$HOME/.dsh}" webFor a new isolated source installation, use the same home and package-local host for installation, readback, launch, and removal:
cd packages/dsh-loopx-plugin
export DSH_HOME="$HOME/.local/state/loopx/dsh-home"
./install.sh
export DSH_BIN="$PWD/node_modules/.bin/dsh"
"$DSH_BIN" --profile web --dump-config
loopx dsh-launch --dsh-bin "$DSH_BIN" web
# When removing this installation:
"$DSH_BIN" plugin --profile web remove dsh-loopx-pluginUse --dsh-home to select profile and Session state, --dsh-agents-home to isolate installed skills, and --dsh-bin when dsh is not on PATH. Arguments after -- are passed to DSH unchanged. The launcher resolves the same write-only machine credential used by the managed executor, then replaces itself with DSH so the credential exists only in the child process environment.
Maintainers can validate the built and packed surfaces with:
pnpm build
pnpm smoke:mcp-transport
pnpm smoke:artifact
pnpm smoke:profile
pnpm smoke:runtime
pnpm smoke:dockerThe runtime smoke creates an isolated temporary DSH profile. Its real web process proves profile composition, automatic initialization before readiness, immediate skill-catalog visibility, boot-manifest discovery, bundle serving, Client materialization, and the loopback Connection fence. A live-disable probe withdraws the bootstrap provider and all package rows while checking that DSH stays available and LoopX's route retires; a fresh process also boots with the whole package disabled. Separately, a packed supported-DSH Context, Connection, and WebServer with a live Host Session fixture cover same-turn binding discovery, lease-time source reconciliation, status-only updates, pending-watch cancellation, successful actions, and handler disposal through the real HTTP carrier. The served Client is then applied in DSH's real ClientModuleSystem with a VM document harness; that layer covers slot order and coexistence, Session injection, and ordinary-unload/HMR style cleanup, but it is not a browser-mounted React interaction. These layers do not replace the owner-reviewed packed-browser gate: that separate manual layer mounts the served Client at a real DSH URL and exercises Client-to-carrier Start/Pause. Focused Client tests cover Session-generation replacement and old request cancellation without duplicating that matrix in the packed smoke. The Docker smoke packs the current plugin and builds the current LoopX release-candidate wheel, then starts both in a clean Debian container with the DSH 0.1.5-rc.2 release candidate. It proves PEP 668-compatible private installation, the managed launcher, startup readiness, installed loopx skill files, launch- token authentication, and an authenticated GoalBar read through DSH's shared API carrier. It requires Docker, uv, and network access for base images and never opens a browser or configures a model provider.
A DSH plugin release needs an immutable prebuilt GitHub asset and a qualified install channel in each marketplace named in its closeout. The directory and DSH Plugin Hub have distinct published catalogs. Current Hub releases read https://api.dsh-plugin.org/plugins.en.json and plugins.zh.json; updating the awesome directory does not update those consumers. Marketplace maintainers retain authority over their own catalogs.
Pinned GitHub release installation does not require publishing LoopX on npm. Release-URL installed-state matching shipped in Hub 1.5.0. Qualification must read the actual marketplace's catalog back, select the pinned package, install it, recognize the installed row, update it and remove it successfully. The optional npm channel retains its separate account and trusted-publisher requirements.
For every DSH plugin release:
typecheck, tests, and the built, packed, runtime, profile, and Docker smokes listed above, plus pnpm smoke:registry --tarball . The registry smoke serves the real packed bytes on loopback and invokes DSH's unversioned package-name installer; it publishes nothing. CI repeats this installation and removal on Linux and Windows. Qualification uses pnpm 10.33.0; use that version for reproducible source and isolated-registry checks.
examples/release/release-readiness-doc-smoke.py with one --surface for every optional capability changed by the release.
publish both the version tag and dsh-loopx-plugin-.tgz asset.
Download the remote asset and verify that its SHA-256 matches the local package before advertising it. For the npm channel, publish that same tarball, including its compiled Host, Client, Driver and initializer:
npm whoami
npm publish ./dsh-loopx-plugin-VERSION.tgz --access public --tag latest
node scripts/verify-distribution.mjs --tarball ./dsh-loopx-plugin-VERSION.tgzlatest intentionally names the qualified plugin candidate, because the marketplace installs its unversioned npm name. Do not substitute a beta-only tag or publish the monorepo root. The readback checks metadata, tag, downloaded bytes and the repository search used by DSH Hub. A missing package, wrong artifact or search-index delay fails verification; publishing alone does not complete marketplace recovery. npm account authentication or configured trusted publishing belongs to the release operator.
For token-free CI publication, configure the package's npm Trusted Publisher with organization loopx-project, repository loopx, and workflow filename dsh-plugin-publish.yml, permitting npm publish. Then dispatch Publish DSH Plugin to npm on the existing published plugin tag, using that same tag for the release_tag input. This keeps npm provenance on the artifact's commit. The workflow requires a merged tag, consumes its GitHub asset without rebuilding, and verifies npm bytes and discovery. It neither creates a GitHub release nor replaces npm account ownership or the release guide gate.
awesome-dsh-plugin, update onlydata/plugins/loopx-project__loopx--packages-dsh-loopx-plugin.yml to the new immutable asset URL. Confirm the URL resolves, then run node scripts/generate-readme.mjs --check and git diff --check.
closeout. Separately verify the installed Hub's catalog source at the released Hub revision. Read both language feeds and the website's install command; for the LoopX row, check the ic and igc targets against the immutable release URL. Route stale Hub metadata to its existing data-correction issue channel. Keep that marketplace's adoption open until its actual consumer resolves and installs the released package. A merged directory PR, another catalog's listing, or an upgraded Hub cannot establish that postcondition.
src/observer.ts, exported as dsh-loopx-plugin/observer, is the dsh-session-events provider for the LoopX capability: an L1 shadow observer that consumes read-only harness events and appends compact, public-safe envelopes plus an observer stats record to /reliability_diagnostics/by-goal/.ndjson, where sha256 is the lowercase digest of the exact UTF-8 Goal id. Upgrade the CLI and plugin together. An existing legacy filename blocks flushes with LegacyDiagnosticLedgerError until the preserves its history; readback never silently migrates it. It is a separate Cordis row and bundle from the Driver, with no Driver or Agent injection and no shared send path. It never calls agent.send, touches the inbox, invokes the LoopX CLI, schedules, retries, stops, or resumes anything. Every hook body and every flush is isolated, so an observer failure is counted into the receipt instead of reaching DSH. This is module and hook isolation, not an OS-process-isolation claim.
Before its first append, the producer applies the same recursive local-path, credential-like value, and credential-field guard as the Python contract. Unsafe event tokens or ids are counted as public_safety_violation and never reach ledger bytes; CLI ingest independently re-validates persisted records.
It is off unless one exact goal, DSH session, and complete run identity are declared before DSH starts:
export LOOPX_DSH_SHADOW_OBSERVER_GOAL_ID=<goal-id>
export LOOPX_DSH_SHADOW_OBSERVER_SESSION_ID=<session-id>
export LOOPX_DSH_SHADOW_OBSERVER_RUN_IDENTITY_JSON='{"worker_id":"<worker>","model_id":"<model>","task_id":"<task>","environment_id":"<environment>","tools_id":"<tools>","budget_id":"<budget>","adapter_revision":"<adapter-revision>","observer_revision":"<observer-revision>"}'
# optional: LOOPX_DSH_SHADOW_OBSERVER_LEDGER_DIR, LOOPX_DSH_SHADOW_OBSERVER_BUFFER_BOUND (default 256)
loopx reliability-diagnostics receipt --goal-id <goal-id> --format json
loopx reliability-diagnostics status --goal-id <goal-id> --format jsonUnless all required variables are valid, the independent observer row registers no hook and writes no file. When enabled, it consumes only session/created, session/event, and session/disposed; it skips the retired token-level assistant/chunk rows older logs still replay, and records tool names, turn and step numbers, typed end reasons, and ids only, never arguments, outputs, prompts, or paths. Events for any session other than the exact configured session are rejected as identity_invalid. The stats record pins worker/model/task/environment/tools/ budget plus adapter and observer revisions, declares source coverage, and proves count conservation. Sequence gaps, bounded-buffer drops, flush attempts, declared clock uncertainty, and the empty outbound and influence fields make the run's admissibility auditable from the receipt.
This is an experimental adapter implementing the RFC's P0 prototype components. It does not establish the RFC's P0 exit: C0 fidelity, a qualifying C1 run, and measured observer overhead remain separate evidence gates.
The independently loaded dsh-loopx-plugin/native-operation-context subpath registers one read-only model tool, loopx_operation_context. It is absent from the default plugin tree and cordis.patch.yml; installing the package does not activate it. An explicit SDK Loader patch can load the built module:
- insert:
- id: loopx-native-operation-context
name: file:///absolute/path/to/dsh-loopx-plugin/lib/native-operation-context.jsThe tool accepts {} only. It derives the calling live session and open Turn from DSH's agent and session-projection services; caller-supplied identities, closed Turns, cancelled calls and disposed or shadowed tool registrations fail. Only provider, model and reasoning-effort options are returned. Other agent options, including credentials, are excluded. Profile options are observations, not HTTP wire attestation; wire_profile_verified and execution_allowed are always false. This module creates no Core actor, grant, binding, approval or account access, and consumes no approval.
The initial runtime qualification uses the Python SDK and bundled DSH 0.1.5rc1: a real native tool call returned the matching SDK session and open Turn. This does not qualify other DSH versions or the complete managed operation journey. From a source checkout, build and verify registration using an interpreter with the selected deepseek-harness SDK installed:
pnpm --dir packages/dsh-loopx-plugin build
"$SDK_PYTHON" packages/dsh-loopx-plugin/smoke/dsh-native-context-sdk-smoke.py \
--module packages/dsh-loopx-plugin/lib/native-operation-context.js \
--provider deepseek-official --model deepseek-flashThis smoke initializes the real SDK with an isolated temporary home and dummy credentials, checks the runtime's schema registration, and makes zero model requests. It does not execute a Turn or test financial operations. Remove the explicit Loader row to disable the module, then restart the owning SDK runtime; the default plugin tree remains unchanged. Existing active sessions must be closed by their owner rather than treated as revoked by editing a patch file.
The read-only module alone delivers no frontend or Lark operation path.
dsh-loopx-plugin/native-operation is a separate, explicit Loader module for the internal OwnedDshOperationHost. It registers loopx_operation with an absolute, parent-owned Unix socket supplied by the host; it is absent from the default exports and patch. Installing the package grants no execution access.
The host retains the original SDK stdio connection across separately admitted Turns. Kernel peer PID, native session/Turn/call ID, exact native arguments and the observed provider/model/effort must match before dispatch to the existing Core operation handler. The existing Turn session file and typed operation store own profile binding, revocation, approval, first consumption and outcome; there is no second approval store or public actor/proof/consume endpoint. Changing the module/package JS, model profile or session requires fresh admission and approval. Transport loss never permits an automatic effect retry.
The real SDK/bundled runtime 0.1.5rc1 qualifies two Turns on one retained connection with a scripted loopback provider: prepare, reject before approval, fixture confirmation, inspect, one permitted consumption, rejected repeat and canonical not_executed outcome. Synthetic confirmation is not human approval; no venue/account effect or paid model call is involved. The read-only real-model probe above and this integrated synthetic-provider test prove different stages.
SDK 0.1.5rc1 cannot reload persisted sessions (session already exists); a new host still refuses that version's resume before runtime launch. An isolated candidate uses Python SDK 0.2.1a3, built with the official wheel script from upstream source 2fbf4359, and an explicit runtime_bin pointing to npm @deepseek-ai/dsh@0.2.1-alpha.3. The SDK's public resume_session restores the same persisted identity without sending input. The host pins SDK files, the executable/Node and complete npm closure into the immutable profile; changes require fresh admission/approval. File/SQLite tests close the first process, restore the original session and repeat the operation sequence. Missing or unreadable history refuses without a provider call, replacement binding or reusable failed client. This candidate does not qualify the default plugin's peer range or a published Python release.
Public CLI/delegation activation, frontend/Lark original-card return and actual financial execution remain unqualified. The public managed-operation preflight remains Codex-only until those entry points are integrated. Disable by omitting this explicit module and closing its owned host; do not interpret patch removal as revoking an already running process.
The GoalBar carrier uses Connection's authenticated /api/loopx.goalbar Fetch route. Explicit callers of the deprecated RPC registration can still register /loopx; plugin startup does not select it automatically. Both pass Connection's Host/Origin trust fence and browser authentication, and this package adds no second credential of its own. The deployment's reachability policy — loopback by default, or declared trustedHosts — decides which browsers can reach the host at all; Phase 1 does not support LAN or remote browsers. The browser supplies only its injected DSH Session id and, for an action, the last validated Goal/Agent pair. The Host re-derives cwd and thread identity from the live DSH Agent, freshly resolves the binding, and executes only fixed LoopX argv.
The wire allowlist contains ids, activation, live Agent status, full-lane counts, cursors, opaque source rev