Byte-Naut/dsh-plugin-probe

dsh-plugin-probe

Cordis service binding diagnostics for DeepSeek Harness — shows target vs committed binding state and why a plugin is stuck in PENDING

待分类cordisdeepseek-harnessdiagnostics

dsh-plugin-probe

Runtime diagnostics for Cordis service binding failures in DeepSeek Harness.

When a plugin is installed but never becomes active, the usual tools tell you that it is stuck in PENDING — not why. This plugin answers the why by reading two layers that Cordis maintains but no official inspector exposes: the target binding (what a consumer declared it wants) and the committed binding (what it actually received). By comparing the two, it can tell the difference between "no provider exists", "a provider switch is still in flight", and "Cordis could not observe the committed store".

The problem it solves

Two recurring failure patterns in the dsh community have no existing diagnostic:

Service removed or renamed (#7445, #5017, #5599): after a dsh update renames or removes a service, plugins that depended on it park in PENDING. The error surface is a misleading "client-half failed" or silence. There is no built-in way to name which service is missing.

Duplicate module instance / Symbol split (#8287, #6529): pnpm installs a second copy of an @deepseek-ai/* package inside the profile. The service registers fine in one module's Symbol registry, but consumers built against the other copy cannot see it. Tools appear installed; every call silently fails.

In both cases binding_trace({ diagnose: true }) names the stuck component, the missing or unresolvable service, and a concrete next step.

Tools

  • binding_trace — normalized snapshot: which components are PENDING or FAILED, what each fiber declared as its target service provider, what Cordis actually committed, and where the two disagree. Accepts an optional focus to return only the connected slice for one plugin or service. With diagnose: true, adds findings with suggested next steps.
  • binding_assure — pure checker: rejects proposals that treat UNKNOWN binding state as a known fact before acting on it.

Diagnostic rules

CodeSeverityTrigger
PLUGIN_LOAD_FAILEDERRORA visible component's state is FAILED
MISSING_SERVICE_DEPENDENCYERRORA PENDING fiber's target binding is KNOWN_ABSENT — no provider exists
SERVICE_PROVIDER_MISMATCHWARNTarget and committed bindings name different known providers
SERVICE_PROVIDER_CONFLICTWARNMore than one visible provider for one service key
SERVICE_BINDING_UNRESOLVABLEWARNTarget is known but committed binding is UNKNOWN

Each finding includes a suggestion field naming the specific components and services involved, pointing to the most likely cause and a concrete next step.

How target vs committed binding differs from what cordisInspect already provides

The official cordisInspect providers (Service, Event, Config, Tool) read reflect.store — the provider side of the registry. They answer "which services are registered and visible". They do not read fiber._store (the target store) or fiber.store (the committed store) on the consumer side. Those two fields are what this plugin observes, and the difference between them is the diagnostic signal that neither the official tools nor static scanners can produce.

Integration: cordisInspect provider and exposure setting

When @deepseek-ai/dsh-cordis-host-runner is mounted, this plugin registers a read-only BindingTrace provider with the official cordisInspect registry. The model reaches it through cordis_inspect_list / cordis_inspect_query from @deepseek-ai/dsh-tool-cordis.

The exposure config decides whether the two direct tools are also registered:

exposureInspect providerDirect toolsUse when
auto (default)when the registry resolvesalwaysunknown preset
inspectwhen the registry resolvesonly as fallbackpreset mounts dsh-tool-cordis
toolsneveralwaystools only

Other plugins can consume the state directly without a tool call:

const state = ctx.get('bindingTraceState')
if (state !== undefined) {
  const findings = state.diagnose()    // [] before first capture
  const slice = state.capture('clock') // one fresh capture
}

Install

Pack and add to a profile:

npm install
npm pack --workspace dsh-plugin-probe
dsh plugin --profile web add ./dsh-plugin-probe-0.1.0.tgz

The bundle patch (cordis.patch.yml) inserts the plugin row automatically on install. Without cordis-host-runner, dynamic package state is reported UNAVAILABLE and the inspect provider is not registered — the direct tools still work.

Tested range

dsh 0.2.0-rc.2 and 0.2.1-alpha.1, Cordis 4.0.4 and 4.0.5-alpha.1, Node.js ^22.19. Two defects found on a live 0.2.0-rc.2 install are fixed and covered by tests: provider registration depended on Loader row order, and focus expanded to nearly the whole graph.

See docs/limits.md for known gaps.