Plugin SDK Development and Releases
Development, verification, release tools and 1.2 workflows, incremental cache, external tools and public LSP bridge.
Development, verification and release guidance for DDS Plugin SDK 1.2.0. Security audit and vulnerability validation are pending; stable API status and functional checks do not constitute security acceptance.
SDK installation and API guide
Development Templates and Generation
Choose command, language, theme, job, browser or configuration. init --dry-run reports the destination, file inventory, hashes and conflicts without writing or installing. Normal init requires a new real directory. Each template includes source, manifest, disclosure, license/notice, tests, a typed consumer and an executable example. Browser and configuration templates include a loopback demo. Generated dependencies pin the exact GitHub archive.
npx --no-install dds-plugin init example-plugin --template configuration --dry-run
npx --no-install dds-plugin init example-plugin --template configuration
cd example-plugin
npm install --ignore-scripts
npm run doctor
npm test
npm run typecheck
npm run example
npm run browserdds-dev.json is bounded JSON data for command schemas, settings, locale catalogs and theme data. generate emits runtime JSON, ESM exports, raw/validated TypeScript input types, output/settings types, JSON Schema and theme XML. JSON Schema defaults are annotations; only SDK input validation applies defaults. Generation does not import your plugin. doctor checks drift, metadata, missing modules and whether generated runtime files are included in the package allowlist.
npx --no-install dds-plugin generate . --check
npx --no-install dds-plugin generate . --dry-run
# Review the new files, then use the previous digest from the report:
npx --no-install dds-plugin generate . --expected-digest <previous-digest>Replacement requires the exact prior digest and unchanged generated bytes. Manual edits, extra files, links and stale locks stop replacement. Failures remove only unchanged entries owned by that attempt and retain modified or uncertain entries for inspection. Files are limited to 256, 1 MiB each and 4 MiB total. The lock coordinates cooperative generators; it is not protection against a hostile concurrent filesystem writer or a cross-directory atomic transaction. Proprietary templates require caller-supplied terms and preserve inherited SDK license/notice files.
Deterministic Testing and Replay
createScenarioHost from /testing explicitly mounts selected in-memory file, backend, settings, secret and job fixtures. It starts with no grants or capabilities. createTestClock supplies seeded IDs, time and timers without patching globals; equal-time timers retain insertion order. Await clock advancement to unblock virtual waits. The generated UUIDs are test data, not cryptographic entropy. Existing createTestHost defaults remain compatible.
import {createScenarioHost} from '@altifigence/dds-plugin-sdk/testing';
const scenario = createScenarioHost({seed: 7, start: 1000,
files: {'example.txt': 'synthetic'}, grants: ['workspace.read'],
});
try {
// Activate your explicitly imported test plugin on scenario.host.
scenario.faults.enqueue({operation: 'file.read', kind: 'delay', delayMs: 25});
// Start its command, then await scenario.clock.advance(25).
} finally {
await scenario.dispose();
scenario.assertClean();
}Fault ports model delays, denials, disconnects, corruption, exhaustion and dropped calls; event fixtures may be dropped, duplicated or reversed without repeating external effects. replaceGrants deactivates plugins losing authority. Memory job snapshots validate identity, revision and hashes and model interrupted recovery without automatic execution. These fixtures do not emulate filesystem durability or discover operating-system handles. A separate owner ledger tracks explicitly registered resources. Teardown preserves pending counts for callbacks that ignore cancellation until they actually settle. Settings inspect is now readable after disposal; data reads still reject.
Recording requires synthetic: true and an explicit bounded fixture inventory. Exported traces contain only operation kinds, fixture IDs, timing, seed/version and chained hashes. Use nonsensitive IDs; hashes do not anonymize guessable data and the SDK cannot classify arbitrary input as synthetic. Pure replay checks order, hashes and fixture identity and returns selected fixture outputs; it accepts no effect callback. Limits include 64 fixtures, 1,024 events and a 1 MiB trace. Run the packaged development-tools example for faults, recovery, privacy and cleanup checks.
Local Diagnostics and Debugging
import {createDiagnosticSession, profileHost}
from '@altifigence/dds-plugin-sdk/diagnostics';
const session = createDiagnosticSession({enabled: true, sampleEvery: 10});
const measured = profileHost(host, session);
try {
await measured.executeCommand('example', 'run', {});
} finally {
measured.dispose();
console.log(session.snapshot());
session.dispose();
}Diagnostics are off by default and local only. Reports contain fixed operation/status/error codes, correlation IDs, durations and resource counts; there is no API for document bodies, paths, inputs, output bodies or arbitrary exception text. Byte counts, queue depth and memory figures are explicit owner estimates. profileTransport measures until the wrapped call resolves, which for fetch is response headers rather than body completion. Completed records use a bounded ring and passive expiry; there are no diagnostic background timers or uploads. Defaults are 128 events/60 seconds; maximums are 256 events/5 minutes, 64 in-flight spans and 256 KiB per report.
npx --no-install dds-plugin dev . --trust-local-code --profile --command greet --input '{"name":"Ada"}'
npx --no-install dds-plugin dev . --trust-local-code --debug --debug-wait --timeout-ms 30000 --command greet --input '{"name":"Ada"}'Debug mode exposes only an ephemeral 127.0.0.1 inspector in the owned child process. --debug-wait pauses before importing the plugin and requires --debug. The total run budget includes debugger wait and is at most 30 seconds. Completion, cancellation and timeout terminate the owned child and inspector. Both profiling and debugging require explicit trust in local code; neither is a sandbox. Crashes or forced termination can omit the profile report, and raw plugin stdout/stderr remain a separate bounded stream that is not automatically redacted.
Development tools · Testing · Diagnostics · Compatibility
Host Conformance
The /conformance module runs versioned synthetic probes against your explicitly supplied host, settings, workspace, localization, testing, diagnostics and development adapters. It distinguishes supported, unsupported and failed profiles and includes host/version/runtime/platform, check ID, timing and cleanup. A declared feature with a missing or broken adapter fails; unknown optional features are recorded without probing. Commands, permissions and cancellation are required by default.
import {runConformance, formatConformanceReport}
from '@altifigence/dds-plugin-sdk/conformance';
import {createPluginHost} from '@altifigence/dds-plugin-sdk';
const report = await runConformance({
identity: {host: 'My host', version: '1.0.0', runtime: 'Node 24', platform: 'linux-x64'},
features: ['commands', 'permissions', 'cancellation'],
adapters: {host: options => createPluginHost(options)},
});
console.log(formatConformanceReport(report));Replace the host factory with your adapter and run your plugin tests as well. The Node /conformance-node helper creates only fresh temporary fixtures and ephemeral loopback servers. The browser example runs available browser profiles and reports absent Node features as unsupported. Quick probes sample contracts; linked examples and release tests cover larger language, recovery and storage paths. A report is test evidence, not a trust certificate.
Deadlines default to 10 seconds per case, at most 30 seconds. Timeout or cancellation stops later cases; cleanup failure fails the case, and pending cleanup stays unverified. Trusted in-process adapters can block synchronously and retain ambient authority. Reports exclude provider error bodies, payloads, tokens and paths; choose nonsensitive identity labels. No report is uploaded automatically.
SDK Support and Migration
API_SUPPORT.json lists every exported module, runtime name, declaration, declaration digest, environment and stability. Stable 1.x APIs follow semantic versioning: compatible additions use a minor release and incompatible stable changes require a new major. artifact-resume-browser remains experimental and needs an exact SDK/browser version with fresh browser acceptance. Optional capability discovery and current permissions remain required.
The stable-line policy applies from 1.0.0. The latest stable minor receives ordinary fixes; the preceding minor remains eligible for critical security fixes for 90 days within a supported runtime. No stable API is deprecated in 1.0.0. Deprecations are announced for at least two minor releases and six months before major-version removal. RCs and previews are superseded. This open-source policy does not promise commercial response times.
Server and CLI acceptance covers Windows/Linux with patched Node 22 or 24, and declarations with TypeScript 5.9.3. Node 22 support ends 2027-04-30 and Node 24 ends 2028-04-30. Release receipts identify exact patch versions, OS images and browser build. Other runtimes and browser/storage combinations need their own acceptance. SDK runtime npm dependencies remain empty.
Stable 1.0 plugins use >=1.0.0 <2.0.0; raise the minimum when adopting a later API. RC1 packages retain their exact 1.0.0-rc.1 peer. Revalidate and publish a new plugin version to change it; keep prior archives immutable. Legacy archives are interoperability inputs, not maintained lines. After restart establish a fresh connection and current grants; recovery reads committed state without rerunning work.
Release Acceptance
The security audit and vulnerability validation are pending under the owner's 2026-10-05 deferral. Functional, compatibility and performance results do not constitute security acceptance. The retained review will resume separately; this release must not be described as having passed that audit.
The combined fixture concurrently exercises language/settings, reviewed edits, command jobs, project watch, upload/download and retained storage. It checks interruptions, malformed responses, revocation, generation changes, recovery and resource cleanup. Separate filesystem/process tests cover killed children, corruption, failed writes, expiry and ignored cancellation. The RC acceptance report links reproducible commands and the boundaries of each result.
Performance records five fresh-process samples per Windows/Linux and Node 22/24 profile, including median/spread, CPU time, sampled memory, import/startup/watch timing and logical disk/HTTP payload counts. Baseline thresholds come from those measured samples and are coarse regression guards, not a latency SLA. They do not measure physical disk traffic or guarantee every operating-system handle is discovered.
npm ci --ignore-scripts
npm run check
npm run example:conformance -- --json
npm run example:combined -- --faults
npm run benchmark:combined
npm run example:conformance-browserConformance · API inventory · Support policy · RC acceptance
Stable 1.0 Release Contents
The original 1.0 package includes 38 exports and 86 schemas with declarations, examples, LICENSE and NOTICE. 1.1 adds the release tools below; 1.2 adds the workflow/cache/tool/LSP sections below. Release receipts distinguish exact source/CI/digests, fresh consumers and reused browser evidence.
To downgrade, stop owned work and explicitly select retained compatible SDK/plugin archives and a configuration export. Review current grants and create a fresh connection. Result recovery is readback-only; external effects and incompatible settings are not automatically undone. Test the formats and optional features actually used.
Release contents, migration and support
Offline Bundles and SBOM
SDK 1.1 adds five optional Node-only entry points: /bundles, /provenance, /updates, /updates-node and /upstream. The package contains 43 exports, 96 schemas, declarations and runnable examples with zero runtime npm dependencies. Existing 1.0 APIs and unsigned DDS .tgz archives remain compatible.
lockBundleDependency locks a reviewed ESM/CommonJS file tree to an exact version, HTTPS source, canonical file digest, dependency map, LICENSE/NOTICE and explicit redistribution decision. The digest describes the reviewed tree; it is not an upstream archive hash. createPluginBundle embeds the original DDS plugin archive and release metadata, a single-version acyclic dependency graph and deterministic CycloneDX 1.6 SBOM.
verifyPluginBundle checks the exact bounded byte snapshot. installPluginBundle requires its expectedSha256, approved: true and a new directory under an operator-owned parent. It does not run npm, lifecycle scripts, downloads or plugin code. Dependencies inherit no new grants. The host SDK is a separate dependency. Native addons, export maps and arbitrary npm dependency resolution are outside this format.
Limits: 32 dependency packages, 1,024 expanded files, 4 MiB per dependency file, 32 MiB expanded content and 48 MiB encoded bundle. The original root archive has its own smaller limits. Missing or conflicting versions, cycles, orphan dependencies, changed hashes, missing licenses/NOTICE, paths/links and file-directory collisions are rejected. Failed installs retain the new destination for inspection. Exclude concurrent writers; this tool is not an OS sandbox.
Detached Signatures and Operator Trust
createProvenanceStatement binds the exact bundle name/version/SHA-256, publisher, source revision and issue/expiry times. signPluginProvenance uses a caller-owned Ed25519 KeyObject. canonicalProvenancePayload exposes DDS-PROVENANCE-V1 followed by canonical JSON so another signer can reproduce the same payload. The SDK supplies no private signing key or DDS product signing authority.
verifyPluginProvenance takes operator-selected trust roots, publisher/subject bindings, current time, key validity/revocation and timestamped revocation evidence. Offline verification uses supplied evidence and applies the same freshness budget; it never fetches fresh revocation information itself. A new package key is untrusted until the operator adds it. Explicit overlapping roots support rotation. Maximum clock skew is five minutes and maximum evidence age is 30 days; select stricter limits when needed.
Receipts keep checksum, signature, publisher and policy separate and always return executionAuthorized: false. A signature does not prove code safety or grant execution, data access or sandbox authority. Older unsigned packages require envelope: null and allowUnsigned: true, still reporting unsigned and unverified publisher. Security audit and vulnerability validation remain pending independently.
Review, Activate and Roll Back
createPluginUpdatePlan compares old/new version, API, grants, dependency sources/hashes, declared tools, licenses, settings hashes, migration identity, signature and key, then fixes the review digest. createPluginUpdateController owns the current authorized host and settings plus operator getPolicy/prepare ports. Stage verifies and snapshots the candidate; approve must match the exact plan digest, grants and key ID. Activate checks current settings and refreshes trust before and after preparing a separate candidate host.
wait defers activation while jobs are running. retain-old leaves old jobs on their original host/settings/hash and sends new executions to the new host after the switch. execute returns the plugin hash alongside each result. Jobs are not implicitly cancelled. Settings replacement invalidates a pending approval; concurrent changes and failed preparation preserve or explicitly report the prior state. Rollback stages the old package/settings as a new reviewed update and requires current trust and fresh approval.
Preparation and migrations run through operator-owned trusted ports. Neither rollback nor failure undoes external files, network requests or other effects. reversible is review metadata rather than an automatic undo promise. A Node journal is append-only, single-writer and outside the workspace, with exact revision CAS and bounds of 256 records / 128 KiB per envelope / 8 MiB total. Archive under operator control before opening a fresh journal at the limit.
inspectNodeUpdateJournal reads persisted state without replay. A crash during preparing or an ambiguous acknowledgement requires explicit host/settings readback; reconcilePluginUpdateJournal records an approved known old/new digest and settings hash. Corrupt tails need operator inspection/repair. recoverStaleLock only recovers a same-machine writer proved dead. This does not promise a cross-process host/settings transaction or universal power-loss atomicity.
Explicit Upstream Checks and Candidates
fetchUpstreamArtifact needs an explicit invocation, enabled: true, exact source URL/version/digest, exact URL allowlist, offline policy, byte budget and deadline. Redirect targets must also be allowlisted. It sends no cookies or auth headers, retries nothing automatically and reports verified / digest-mismatch / unavailable / offline / unverified with observation time. Changed tags or hashes need new review. Loopback HTTP is available only through an explicit fixture option.
Adapters can publish a reviewed upstream-manifest containing API inventory, exact source revision, full license/NOTICE and file hashes. inspectUpstreamManifest ties that metadata to downloaded bytes; it does not analyze arbitrary source code or infer redistribution permission. createUpstreamCandidate returns API/file/license diffs and a before-digest/replacement-source patch. Matching an exact version matrix without a developer functional check stays unverified; a missing required API is unsupported.
A supported candidate still requires human review. Its automaticActions array is empty; these APIs do not create a branch, merge, publish, approve new grants or install a monitor. The host owns adapter test execution and cancellation. The complete public example below exercises local fixtures only. Workflow/cache/tool/LSP APIs are available in the 1.2 sections below.
node node_modules/@altifigence/dds-plugin-sdk/examples/release-tools/run.mjsTypes, API, limits and complete runnable source
Command Workflows and Explicit Recovery
SDK 1.2 adds seven optional exports: /workflows, /workflows-node, /workflow-cache, /workflow-cache-node, /tool-streams, /tool-streams-node and /lsp-node. The current package has 50 exports, 107 schemas, TypeScript declarations and independent installed examples, with zero runtime npm dependencies. Only /tool-streams is portable to the browser; the other new exports require Node. Existing workspace protocol and 1.x APIs remain compatible. A plugin importing a new 1.2 API must declare 1.2.0 as its minimum SDK version.
prepareWorkflowPlan validates registered command IDs, unique steps, acyclic dependencies, closed input/output data schemas and required output bindings before execution. Each input is a literal {value} or a {step, path} binding to an explicit dependency. Schema constraints must match exactly. The immutable plan binds its commands, grants, scope and inputs to a SHA-256. run requires approved: true and that exact reviewed digest. Host authorize and execute ports remain operator-owned.
createCommandJobExecutor connects an isolated existing PluginHost selected by resolveHost, which returns the exact host scope, step grants and plugin hash. Grants are never combined across steps. Current authorization is checked before execution, after results and before reuse. continue completes independent branches and blocks failed descendants; fail-fast cancels remaining steps. Records retain parent job/attempt IDs, individual jobs, input/output digests, artifacts, reasons and timestamps. Cached hits have no fresh job ID and cannot claim mutable job artifacts.
recover reads a stored checkpoint and reports pending/running work as interrupted without execution. A manual resume supplies the exact previous record and previousAttemptId in a new approval, creates a new attempt and retains only matching unexpired successful results. retrySteps reruns selected steps and their descendants even in an unordered DAG. Expired output requires an explicit retry selection; changed schema, input, grants or plugin hash requires a new plan. An executor ignoring cancellation remains counted as unsettled and prevents overlapping retries.
createNodeWorkflowStore uses real disjoint store/workspace directories, scope and filesystem identity markers, one writer, checksummed envelopes and CAS checkpoints. After a known crash, explicit recoverStaleLock only accepts a proven-dead same-machine owner. Default cleanup handles recognized corrupt records and unfinished writes while preserving unknown files/links. cleanup({expiredBefore}) can also remove expired terminal records; active records remain for recovery. Windows does not claim directory fsync or power-loss durability. Limits: 64 steps, 8 concurrent steps, 10-minute workflow deadline, 64 KiB per result, 1 MiB combined outputs, 2 MiB records, 64 retained records and at most 24-hour partial-result retention.
Types, API, limits and complete runnable examples
Deterministic Cache and Incremental Execution
fingerprintWorkflowInputs hashes actual file bytes plus SDK version, workspace/security scope, command schema/input, plugin/tool hashes, settings, declared environment and grants. mtime and path alone are never content identities. The operator explicitly declares optIn, deterministic, declaredInputsComplete and secretDependent. Unknown or incomplete input, nondeterminism, secret dependence, missing/undeclared environment and secret-reference inputs bypass cache with a reason. The host must also exclude raw secrets and side effects; the SDK cannot infer hidden inputs.
createWorkflowCache rechecks current authorization on lookup/fill/after-fill/hit/return and verifies value hashes, scope, grants and expiry. Simultaneous eligible misses share one fill; cancelling one waiter does not cancel others. Expired or damaged values are misses. TTL/LRU, entry/value budgets and owned-store cleanup control storage; write failures remain computed results with an explicit reason. Secret-reference results are never retained. Fingerprint limits are 64 files, 4 MiB each and 16 MiB total; cache limits are 512 entries, 16 MiB retained value bytes, eight fills and 60 seconds per fill.
The workflow example performs cache lookup only after current dependencies succeed. A changed file invalidates its step; changed outputs invalidate dependent input fingerprints. A failed dependency blocks the parent before looking up a cached parent result. Receipts distinguish hit, miss, shared and bypass, actual execution from reuse, cache counters, storage bytes and local timings. Durable cache state uses disjoint owner directories and atomic replacement, with orphan-write/corruption recovery; it does not delete source files.
Types, API, limits and complete runnable examples
Registered Tool Output Streams
createToolStreamParser is a portable, bounded UTF-8 JSONL/text decoder. Await write(bytes, stdout/stderr) for backpressure and finish only after both streams end. It preserves split multibyte characters and final partial lines, emitting correlated log, progress, diagnostic and unknown events. Malformed UTF-8 and hard limits stop parsing. Relative diagnostic paths, ordered positions and severities are validated; the consuming editor must also validate positions against current document text. createJobToolEventSink connects progress/logs to an existing JobReporter and leaves diagnostics to a caller-owned sink.
The optional Node runner accepts fixed operator registrations: backend/tool/version, absolute executable and selected implementation pins, exact version probe, explicit environment, closed input schema and required scalar argument slots. File slots must name existing relative workspace files. A plugin invocation selects only an already registered tool/version and validated input; it cannot choose a shell or executable. Current authorization is checked before preparation/start, on events and after completion. Receipts retain exit code, cancellation/failure reason and output statistics.
Known single-line secret/path literals are masked after line assembly, including split chunks; encoded or unknown secrets are not automatically detected. The runner owns only its direct child/pipes and closes them on cancellation or close. It neither scans nor kills unrelated or descendant process trees and is not an OS sandbox. Limits: 64 KiB chunks, 16 KiB lines, 2 MiB total output, 4,096 events, eight queued writes, five-second sinks, 32 tools and four concurrent executions. A separate five-second/16 KiB probe checks the configured version.
The SDK-authored redistributable tool fixture tests fragmented UTF-8/JSONL, trailing output, nonzero exits, cancellation and limits. The actual adapter is TypeScript 5.9.3 with --noEmit --noLib --pretty false and a disposable intrinsic-types fixture producing TS2322. Explicitly supply an existing approved TypeScript root to run it. The SDK never automatically installs or downloads an external tool; supplied hashes do not independently authenticate its publisher.
Types, API, limits and complete runnable examples
Public Stdio LSP Bridge
createLspBridge connects an explicitly approved pinned stdio process to existing SDK language requests/providers. It negotiates the supported LSP 3.17 subset, UTF-16 positions and full snapshots. capabilities reports advertised support separately from successful executions. Supported mappings cover completion, hover, definition, references, flat/hierarchical symbols, signature help, prepare-rename/rename, document/range formatting, code actions, full semantic tokens, folding and inlay hints: 15 SDK features.
syncDocument and closeDocument handle didOpen/didChange/didClose. Current version and generation changes cancel stale work, duplicate active request IDs are rejected, and late replies are ignored. Local URIs must resolve inside the workspace without links; source and edit targets require current authorization and an open or host-provided exact snapshot. Rename/format/action results are conditional workspace-edit proposals with base hashes, never automatically applied edits or executable commands.
Diagnostics are accepted only with the current document version. Unversioned/stale notifications are dropped and counted. Explicitly unsupported features are completion resolve/snippets, code-action resolve, semantic deltas, server commands, dynamic capabilities, resource operations, socket transports and unversioned diagnostics. workspace/applyEdit returns applied:false. Limits: 1 MiB messages, 8 KiB headers, 64 MiB/20,000-message sessions, 16 pending requests and queued writes, 32 documents/4 MiB aggregate text, request deadlines up to 30 seconds and 64 KiB discarded stderr.
close sends shutdown/exit and performs bounded direct-process/pipe cleanup, distinguishing graceful acknowledgement, refused/crashed servers and actual process closure. A server may acknowledge shutdown and still need the owned-process stop. There is no automatic restart or replay: the operator creates a fresh bridge and explicitly resends selected current snapshots. Synthetic tests cover malformed framing, crash/timeout, cancellation/late replies, document races, refused shutdown, unsupported requests and every mapped feature.
The actual independent server check uses community typescript-language-server 5.3.0 with TypeScript 5.9.3: completion, hover, definition, references, symbols, signature help, formatting and semantic tokens passed. Selected implementation files and Node are pinned, tsserver path is fixed and automatic typings acquisition is disabled. This server version omits optional initialize.serverInfo and sends unversioned diagnostics, so its diagnostics are explicitly unsupported by this bridge; versioned diagnostics are verified using the independent synthetic server. The operator must trust the entire installed tool and its OS access.
1.2 acceptance includes independent packed consumers, declarations, 107 schemas, the actual compiler/server adapters and historical public archive interoperability. The workflow example distinguishes durable recovery and explicit retry from automatic replay. Security audit and vulnerability validation remain pending under the owner deferral. This release does not constitute DDS UI, Engine, Cloud scheduler, Marketplace, installer or security-sandbox acceptance.
Types, API, limits and complete runnable examples
node node_modules/@altifigence/dds-plugin-sdk/examples/workflows/run.mjs
node node_modules/@altifigence/dds-plugin-sdk/examples/workflow-tools/run.mjs
node node_modules/@altifigence/dds-plugin-sdk/examples/lsp/run.mjs
node node_modules/@altifigence/dds-plugin-sdk/examples/tool-streams-browser/serve.mjsFor actual adapters, add absolute paths to existing operator-approved installations. Default examples use only SDK-authored fixtures and never download a tool.
node node_modules/@altifigence/dds-plugin-sdk/examples/workflow-tools/run.mjs --typescript-root /absolute/path/to/typescript
node node_modules/@altifigence/dds-plugin-sdk/examples/lsp/run.mjs --typescript-root /absolute/path/to/typescript --language-server-root /absolute/path/to/typescript-language-server