English | 中文
A self-contained standalone repository template for an ESM Cordis plugin targeting DeepSeek Harness 0.2.2-rc.1. Every source file, compiler setting, test fixture, contributor instruction, skill, and build helper used by the repository lives below this root. A DSH host is a runtime consumer of the finished package, not a development input.
| Need | Read |
|---|---|
| Contract rules: plugin forms, manifest, dependencies, display, lifecycle, composition, client, distribution | docs/dsh-plugin-contracts.md |
| End-to-end workflow and stage routing | .agents/skills/dsh-plugin-development/SKILL.md |
| Source, test, and patch layout | src/LAYOUT.md, tests/LAYOUT.md, patches/LAYOUT.md |
| Commands, CI, and release flow | this README and .github/workflows |
.
├── .agents/skills/ # Repository-local plugin development workflow
│ ├── dsh-plugin-development/ # End-to-end coordinator
│ └── dsh-plugin-*/ # Stage skills
├── docs/
│ └── dsh-plugin-contracts.md # Authoritative package and integration contract
├── patches/
│ └── LAYOUT.md # Dependency and DSH-host patch contract
├── scripts/
│ ├── extract-patch.mjs # Host patch regeneration
│ └── patch.sh # Idempotent host patch application
├── src/
│ ├── assets/
│ │ ├── icon.svg # Plugin icon exported through `./icon`
│ │ └── locale/
│ │ ├── en.json # Display metadata
│ │ └── zh.json
│ ├── LAYOUT.md # Growth rules for source modules
│ ├── config.ts # Schemastery schema and defaults
│ ├── index.ts # Loader-facing function-plugin namespace
│ └── runtime.ts # Host boundary and activation
├── tests/
│ ├── LAYOUT.md # Test conventions
│ ├── harness.ts # Shared real-Cordis mount
│ ├── plugin.test.ts # Loader and activation tests
│ └── snapshots/
│ └── LAYOUT.md # Optional visible-output fixtures
├── .oxlintrc.json # Type-aware Oxlint configuration
├── AGENTS.md # Contributor standing orders and navigation
├── cordis.patch.yml # Profile bundle contribution
├── package.json # Exports, peers, engines, bundle metadata
├── pnpm-lock.yaml # Reproducible dependency graph
├── pnpm-workspace.yaml # Package-manager policy
├── tsconfig.json # Compiler and type-aware lint project
├── tsdown.config.ts # Source-to-runtime/declaration build
└── vitest.config.ts # Test runner configuration
docs/dsh-plugin-contracts.md owns the full contract. The orientation points are:
- A function plugin exports
name,inject,Config, andapplyas one ESM namespace and has no default export. engines.nodeis>=24.9.0;engines.dshdeclares the supported DSH range;dsh.manifestVersionanddsh.bundle.patchdescribe the public bundle layer.- Display metadata reaches Plugin Manager through the exported
./locale/*.jsonand./iconresources. This template stores their physical files undersrc/assets/and lists them infiles. @deepseek-ai/cordisand@deepseek-ai/schemasteryare host-supplied peers, duplicated indevDependenciesfor local checks. See dependencies.- A browser face declares
dsh.clientand exports its built bundle at./client.
- Replace package identity in
package.json, the Loader owner, configuration/runtime owners, focused tests, bundle metadata, TypeScript metadata, both READMEs,AGENTS.md, andsrc/assets/. - Choose the exact npm package name. It may be scoped or unscoped; do not assume the template's
@your-scope/dsh-prefix. Replace it only in identity owners, never globally inside.agents/skills/. - Set
engines.dshto the range you support. Keepengines.nodeat Node 24 LTS or newer unless a different host contract is deliberate. - Update
keywords,LICENSE,cordis.patch.yml, and the display title, description, and icon. - Add only the DSH host services the implementation uses. Apply dependencies when placing each package.
- Implement activation and host-boundary behavior in the runtime/service owners, keeping registrations fiber-owned and disposing them in tests.
- Keep every source, compiler, documentation, and project-reference path inside this repository. Do not add
link:orfile:dependencies. - Set
privatetofalseonly when the package's public dependencies and distribution artifacts are ready.
Do not add a default export to a function plugin. Cordis Loader unwraps exports.default ?? exports; a stray default export discards inject, Config, and apply.
Start with dsh-plugin-development for the complete sequence, or invoke one stage directly:
| Skill | Purpose |
|---|---|
| plan | Decide form, dependencies, configuration, compatibility, display, composition, evidence, and distribution. |
| scaffold | Instantiate and baseline-verify a new repository from this template. |
| align | Migrate an existing repository to this toolchain without changing behavior. |
| implement | Implement lifecycle-safe behavior, configuration, metadata, docs, and tests. |
| client | Add a dsh.client browser face, slots, settings forms, and ModuleLoader checks. |
| i18n | Localize browser UI with typed dictionaries and disposal evidence. |
| compose | Install the bundle into a profile and prove activation and compatibility. |
| test | Select the smallest evidence for Loader, behavior, disposal, composition, and artifacts. |
| release | Check packed, Git, or npm release readiness without publishing. |
Keep these directories when copying the template.
Run from this repository root:
pnpm install
pnpm run fmt:check
pnpm run lint
pnpm test
pnpm run build
pnpm pack --dry-run --jsonlint is the type-aware static-analysis gate. test uses the Vitest forks pool; a restricted host that rejects child-process forks can run vitest run --pool=threads locally. build emits the ready-to-pack lib/ runtime and declarations without an install-time build.
- check.yml: runs checks on
mainpushes, pull requests, and manual dispatch, and both build workflows call it. - test-build.yml: manually builds a test package.
- release-build.yml: builds a release package from a
v*.*.*tag or a manual dispatch. - npm-publish.yml: verifies SHA256 and publishes a successful test or release build to npm through OIDC trusted publishing.
A plain main push runs checks only. Test and release builds lead to npm publication when the package's trusted publisher is configured.
For npm setup, version rules, and provenance limits, read release skill.
Install through the plugin channel:
dsh plugin --profile <profile> add <package-or-tarball>Profile startup checks engines.dsh, applies dsh.bundle.patch in bundle order, and reads display metadata without activating the plugin. See manifest and compatibility and bundle composition.
export const name = 'plugin-template'
export const inject: string[] = []
export { Config } from './config.ts'
export { apply } from './runtime.ts'
// src/config.ts
import Schema from '@deepseek-ai/schemastery'
export interface PluginConfig { /* serializable fields */ }
export const Config: Schema<PluginConfig> = Schema.object({ /* validation and defaults */ })
// src/runtime.ts
export function apply(ctx: Context, config: PluginConfig): void { /* effects */ }Config is the schema value Cordis Loader validates; PluginConfig is the public TypeScript shape. Keeping the names distinct avoids the declaration-merge false positive in no-redeclare. A service provider instead default-exports its Service subclass; do not mix the two forms.
Build before packing and inspect the archive:
pnpm run build
pnpm pack --dry-run --jsonThe archive must contain every file promised by main, types, exports, and files, plus the bundle patch and the physical display assets. See build and distribution. Git installs fetch sources; only add a self-contained prepare build when you deliberately distribute that way and document the consumer's build-script approval.
The baseline tests prove Loader-safe ESM exports and schema-resolved activation. Replace the activation assertions with observable behavior and disposal assertions for every registry contribution. Product-visible plugins also need a real Loader/profile composition test in the consuming DSH application; see tests/LAYOUT.md and evidence.