Skip to content

ets-plugin-dsh-workspace-reflect

Verified

@playform/ets-plugin-dsh-workspace-reflect · v0.2.1 · CC0-1.0

The workspace-reflect service: a DeepSeek Harness plugin providing the LATER-STAGE code-block reflective API - the AST-aware rename/connect/replace bundled as ONE call each, over the managed representations (the family map's reflect role; the workspace re

Install

dsh plugin add @playform/ets-plugin-dsh-workspace-reflect

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Readme

@playform/plugin-dsh-workspace-reflect

v0.1.0 - UNPUBLISHED - plan: Workspace-Family/REFLECT

The role

The workspace-reflect service serves the DeepSeek Harness plugin family (the Classic release).

It fills the later stage service-provider role: the code-block reflective ops, the AST-aware rename/connect/replace from a single call each, over the managed representations.

The one-call semantics

Each operation bundles the whole transformation, so one call replaces a tool choreography.

The spans are 1-based and inclusive (the span grammar of the graph).

Op Request Behavior
rename path, startLine, endLine, oldName, newName, scope? The semantics service's scope-resolved plan first (its edits filtered to the operation's scope); the whole-word textual engine as the fallback. Zero occurrences is rejected.
connect fromPath, toPath, symbol? Inserts an import of symbol from the relative specifier of toPath into fromPath; without a symbol, a reference comment. Already-connected is rejected.
replace path, startLine?, endLine?, text, node?, fingerprint? A graph NODE target (the AST source) with its content fingerprint verified before the write; or a plain span (the textual form). The span guard rejects a span outside the file or wider than maxBlockLines.

The AST-aware targeting

A replace may name the frozen node id of the workspace graph (node: "Block:<path>:<line>:body") and the content-derived fingerprint of the node.

The graph (ctx.workspaceGraph, probed and never injected) supplies the span, and the plugin verifies the fingerprint against the current text with the formula of the graph and rewrites only that span.

A mismatch refuses with rejected <path> (fingerprint mismatch) and writes nothing.

With the graph absent the explicit span of the caller is the fallback, and the plugin still verifies the fingerprint.

A rename asks the workspace-semantics service (ctx.workspaceSemantics, probed and never injected) for the scope-resolved plan, which the service may deepen through the harness LSP seam, and it applies the edits of the plan inside the scope of the operation.

The textual whole-word engine is the fallback when the service is absent, refuses, or has no edit in scope.

The reply is part of the type

Every operation returns the CommitReply union (Interface/Reply.ts) and never a boolean or a thrown error:

status: "applied" | "conflict" | "denied" | "rejected" | "recovery-required" | "outcome-unknown";
  • applied.

    The operation is written, and the new version travels with the reply.

  • conflict.

    The version fence failed, so the file moved under the operation and nothing was overwritten.

  • denied.

    The plugin is disabled, so the cold mount answers denied.

  • rejected.

    The plugin refused before any write: a malformed request, an oversized file or span, no matches, an already connected path, a stale fingerprint, or an absent graph.

  • outcome-unknown.

    The write failed in a way that is neither a version conflict nor a confirmed failure.

The publish path and the carry

Writes go only through the guarded write of the factory (the replaceIfVersion fence, the P4 sandbox policy, the stash pre-registration), never through a raw fs write.

After an applied operation the plugin probes the optional workspaceGraph sibling service (never injected) and asks it to re-index the changed file (the reflective carry), and an absent graph is an honest skip.

Service surface (ctx.workspaceReflect)

The surface is rename(op), connect(op), replace(op), and act(op) (the dispatch by kind), all async and all returning the reply union.

The configuration

Every knob is volatile and hot-editable without remounting: logFile (~/.dsh/playform/ets-plugin-dsh-workspace-reflect.log), log, enabled (false - the IDLE-forever posture), propagate (block | file, default block), maxFileBytes (1000000), and maxBlockLines (5000).

The plugin ships disabled and enables only by an explicit ACTIVATE.

The plugin adds no new knob, because the graph and the semantics service are optional siblings.

The policy block (D6) - the write gate

The config carries the shared per-action allowlist (policy: Policy(), composed from the factory's block) and maps it to State.Allow:

action default action default
read auto write approve
index auto commit approve
record auto spawn approve
suggest auto message auto

The reflective WRITES are the gated actions, so replace and rename consult the write verdict before the plugin reads or writes the file.

An approve verdict (the shipped default) refuses the operation with the byte-exact replace held <path> (policy write=approve) or rename held <path> (policy write=approve) line, the reply is rejected with the policy holds the replace|rename (write=approve), and zero writes reach the filesystem.

The fingerprint targeting is unchanged: the policy is the OUTER check, and the fingerprint verification is the inner one.

Flip policy.write to auto (or let a resolved pack override it) to let the next operation reach the write path.

The block is one volatile object, so a policy flip is hot-editable without a remount.

The policy section of a resolved pack overrides the defaults for each action (the wiring is the next refinement).

The ledger

Ledger lines (module-owned, prefixed reflect:): activated, disabled, rename, connect, replace, deepened, denied, rejected, conflict, carried, failed, and the two policy holds replace held <path> (policy write=approve) / rename held <path> (policy write=approve).

The new rejected reasons (fingerprint required for a node target, fingerprint without a node target, fingerprint mismatch, node path mismatch, node not targetable, node not found, graph absent) are documented in SCHEME.md section 5.

The plan

License

CC0-1.0.