Skip to main content
This is an early native integration. The plugin package is 0.0.2, but DSH has no formal minimum host version. A complete real dsh web host-process/model E2E is Not validated.
DSH uses native host hooks. It is not an MCP plugin. Automatic recall and capture run at agent/pre-step; curated pc_* tools call the PowerContext HTTP API directly.

Install and maturity

Setup requires dsh on PATH and the built plugin entrypoint at lib/index.js. It installs the plugin directory with dsh plugin --profile web add. Doctor reads dsh --profile web --dump-config and looks for the exact plugin ID powercontext-dsh. The plugin requires Node.js 20 or newer. That check proves configuration, not a live turn. It does not prove that dsh web loads the plugin, fires the hooks, or renders a permission prompt. The Node.js requirement and a development Cordis dependency are not a formal minimum DSH host version.

Minimal usage

Start the host after the Server:
You normally do not call recall yourself. Send a prompt as usual. Use /pc to inspect Scope and endpoint, and /pc doctor to separate plugin configuration from Server health. Human commands also cover search, remember, flush, and Candidate review. The Agent receives the curated pc_* tools.

Execution flow

The full message batch can improve recall because it includes host and plugin context. Capture is narrower: only text whose source.kind === "user" becomes a Source. A plugin-only batch is never captured as user input. The next() result decides whether injection is valid. Recall happens before next(), but the plugin appends context only when downstream returns kind: "enter". Rejection, missing context, validation failure, or wrapping failure leaves the downstream result alone. next() is never retried to recover from injection failure.

Scope

Scope resolution uses this order:
  1. POWERCONTEXT_DSH_SCOPE_ID or plugin scopeId;
  2. normalized Git remote identity for the session workspace;
  3. a stable SHA-256 identity derived from the workspace path.
DSH does not implement the Git-private Workstream binding or picker used by Codex and Claude Code. The plugin deliberately does not fall back to its process directory. Without session cwd or an explicit Scope, automatic work skips, /pc reports an unscoped state, and a tool returns a stable unscoped result without an HTTP call. This prevents unrelated DSH sessions from sharing Memory by accident. A model tool caller cannot override Scope. The plugin replaces any caller-supplied scope_id with the runtime-resolved value. Derive an explicit Scope from trusted deployment configuration, not model input.

Injection, capture, and flush

PreparedContext must pass the exact v1 schema, status, integer byte-count, UTF-8 byte-count, and configured size checks before injection. The default ceiling is 8,000 bytes; configuration accepts 512 through 32,768 bytes. The injected message is marked as host-supplied, untrusted historical evidence. It exists only for that model entry and is not captured again as user content. Capture writes a deterministic dsh-user-prompt: Source with DSH session and turn provenance. Recall failure does not block capture, and capture failure does not discard valid PreparedContext. Text over 200,000 characters is skipped. Set POWERCONTEXT_DSH_CAPTURE_PROMPTS=false to disable capture. Capture also skips text containing the narrow markers sk-, api_key, or BEGIN PRIVATE. This is a guardrail, not complete secret detection. Disable capture when a prompt must not be persisted. Automatic flush is optional and off by default. With flushOnCapture enabled, a positive capture position starts at most flushMaxCalls attempts and stops early when current_cursor >= position. /pc flush is the explicit human path. If the cursor never catches up, the loop exhausts its bound without proving that the Source was processed. Do not infer Memory from a successful capture log: processing may produce a Candidate, and Review may commit Memory or choose a no-op.

Native tools and permission

The model surface contains 19 curated named HTTP tools, not MCP. They cover Memory, prepare/capture, low-level Handoff, Experience and Skill generation and reads, plus read-only Candidate listing and retrieval. Generic operation invocation, dangerous/admin operations, and Candidate approve/reject/revise are Unsupported on the model surface. High-level create_work_contract, handoff_current_work, acknowledge_handoff, and record_task_outcome are also not registered there, even though related operations exist in the generated HTTP contract. Read tools continue through tools/pre-execute. Named mutations return ask before Memory writes, explicit Source capture, Handoff activation or commit, and Experience or Skill generation. DSH owns the permission UI and allow/deny decision, so these mutations are Host-gated. Unit tests prove the ask classification; the exact real-host UI and denial path are Not validated. Candidate review stays human-controlled. /pc review approve and /pc review reject require the Candidate expected version. Candidate revise is not implemented by /pc. Generating an Experience or Skill Candidate is a separate Host-gated mutation; it is not approval.

Failure behavior

Automatic prepare, validation, capture, optional flush, and message wrapping fail open. The HTTP client bounds responses at 1 MiB, rejects redirects, cancels timed-out requests, and normalizes transport failure to a stable unavailable result. The overall pre-step budget defaults to four seconds; individual requests default to one second. These failures must not replace the downstream Agent result. Explicit durable operations are different. Permission denial and Server error remain visible instead of being reported as success. Missing cwd is an unscoped state, not an empty Memory result.

Negative experiments

Run these checks when upgrading DSH or the plugin:
  • Stop the Server, then send a normal prompt. The Agent should continue without injected context; an explicit write should report failure.
  • Submit a batch containing user and plugin text. Recall should see both; capture should contain only user-originated text. A plugin-only batch should create no prompt Source.
  • Make downstream return a non-enter decision. No plugin message should be appended. This branch exists in code, but a dedicated real-host acceptance test is Not validated.
  • Remove session cwd without configuring Scope. Confirm no HTTP request uses the plugin process directory and that commands and tools report unscoped behavior.
  • Return an unknown PreparedContext field, inconsistent byte count, oversized body, redirect, or slow response. Nothing should be injected, and the downstream decision should survive.
  • Submit capture text containing sk-, api_key, or BEGIN PRIVATE. It should be skipped. Test a different credential shape to confirm that the filter is intentionally narrow.
  • Keep the flush cursor behind the Source position until the call bound is exhausted. The turn should continue without a false processing or Memory claim.
  • Invoke a read and a named mutation. The read should delegate; the mutation should return ask before writing. Test the actual permission UI separately.
  • Inspect the model tools. Candidate approve, reject, and revise, generic invocation, and dangerous/admin operations should be absent.

Unsupported vs Not validated

test_dsh_http_chain.py verifies the native public Client/Server HTTP contract with MCP disabled. The Cordis harness covers plugin call-through against a live Server. Neither starts a real DSH host.

Configuration defaults

Environment variables can override the connection and capture flags. timeoutMs, requestTimeoutMs, maxBytes, and flushMaxCalls are plugin patch settings, not environment variables. Do not put the token in the patch file or the Server URL. Disable capture when the current work must not become Source evidence:

Finish the shared check on this host

What should happen after the OpenAPI contract changes?
  1. Store the answer in a stable Scope with pc_remember. Pass the tools/pre-execute ask first, then confirm the Citation.
  2. Send a new request that will enter the model, and ask the same question.
  3. The recall must include a Citation and appear only in the plugin message appended after enter, starting with PowerContext host-supplied context.
  4. Stop the Server and ask again. Automatic recall may fail. A non-enter downstream result must not be replaced.
  5. Run pc_remember again. The failure must stay visible. Do not disguise it as an empty success.

Completion checklist

Treat the integration as complete only when these results are observable:
  • powercontext doctor dsh finds exact plugin ID powercontext-dsh.
  • Built lib/index.js is installed in the intended web profile, and Node.js is 20 or newer.
  • /pc reports the intended endpoint and runtime-resolved Scope.
  • /pc doctor reaches the Server.
  • Missing cwd makes no HTTP call and returns stable unscoped results.
  • Recall uses the full message batch while capture remains user-only.
  • next() runs once, and injection occurs only after kind: "enter" and exact schema/byte checks.
  • Capture policy accounts for the narrow secret-marker filter and 200,000-character limit.
  • Automatic flush is bounded and is not described as successful processing without cursor evidence.
  • Named mutations produce a host ask.
  • Reads delegate.
  • Denial remains visible.
  • The model has read-only Candidate access and no generic, dangerous, admin, or Candidate-decision tools.
  • Server-down, redirect, invalid-schema, oversized-response, non-enter, and cursor-behind cases have suitable negative coverage.
  • Unsupported, Not validated, and Host-gated claims remain separate.
Continue with OpenCode.