SuperAPI AI Directory

dsh-plugin-lint

Coding & development

View repository

Updated 10-15 20:10

About this skill

DSH Plugin Lint

Review whether a DSH plugin: declarations match artifacts, references to harness actually exist, contract pitfalls are avoided, documentation is in sync, and acceptance evidence can be bound to a candidate.

Development and paradigm basis:references/dsh-plugin-development-standards.md(plugin forms, distribution, tools/events/slot, client artifact contract, typed locale, theme variables, harness reference file index).

This skill does not replace the implementer. When creating a plugin, do a design pre-check first, and come back for formal acceptance after implementation—reviewer and producer do not share responsibility.

Supporting files:

  • scripts/lint.mjs → §1 Mechanical layer (version-aware, rule list below)
  • scripts/test-lint.mjs → Self-test (self-contained fixture, proving each rule catches invalid samples and passes valid controls)
  • config/harness-path.example.yaml → Copy as config/harness-path.local.yaml fill in the local harness repository path (do not commit)
  • templates/plugin-quality-report.md → Report template for formal review (conclusions carry NOT_VERIFIED semantics)

Dependencies

  • Node ≥ 18.6 (uses node:module.isBuiltin), no third-party packages—scripts work out of the box, no installation required.
  • harness traceability requires a local DSH source repository (git when available, also report commit; if unavailable, this item is NOT_VERIFIED).

Working principles

  • Mechanical first, then semantic: what scripts can check (declarations/artifacts/reconciliation) should not waste manual effort.
  • Version-aware, do not freeze assumptions: platform module table, inline safety regexes, theme variables, and package manifest are all read from the current harness source declarations; version and commit go first through the official dsh executable gate (apps/cli/lib/bin.js --version) + git traceability. All empirically tested conclusions in the specification documents must be annotated with the verified version.
  • Every API/event/slot reference to harness must be traced to a source path—do not trust documentation memory (empirical cases: documentation wrote a nonexistent CLI flag, a nonexistent agent/post-step event, an already-removed dsh-client-runtime)。
  • Do not trust self-reported PASS; formal acceptance must bind the boot evidence of the current commit + browser rendering evidence.
  • Objective defects fail-closed;semantic uncertainty only yields WARN / NOT_VERIFIED, never a false PASS。

harness root resolution

lint.mjs Resolve the DSH source repository (harness root) by the following priority:

  1. --harness-root <路径> parameter
  2. Environment variable DSH_HARNESS_ROOT
  3. config/harness-path.local.yaml(inside the skill directory, do not commit)

When all three are missing, mark version-related check items as NOT_VERIFIED(the process does not crash, other checks continue). After successful resolution, report: DSH version (official gate + root manifest, WARN when the two are inconsistent), git commit, number of platform module table entries. All harness dependency checks are based on that version.

Modes

Mode Timing Required
Design pre-check Before writing code Go through the contract section of the development specification; trace event/slot names first
Quick review Third-party/draft §1 Mechanical + §2 Facts + §3 Contract; conclusions carry NOT_VERIFIED
Formal acceptance Before releasing/claiming completion All + §5 candidate binding evidence

§1 Mechanical layer (run scripts/lint.mjs)

node skills/dsh-plugin-lint/scripts/lint.mjs <插件目录> --harness-root <DSH 源码仓库>
node skills/dsh-plugin-lint/scripts/test-lint.mjs   # 自测,退出码 0 = 全部规则自证有效

--json will append a line at the end of the document __DSH_LINT_JSON__{...} machine-readable result. Exit code = number of FAILs.

Section Check content
§0 harness provenance Version (official gate + manifest cross-check), git commit, platform module table/purity regex parsability, config baseline drift
§1 package.json name resolution;@deepseek-ai/dsh-* dependency pinned version vs current harness version drift
§2 dsh.bundle patch file exists, row references package name
§3 exports["."] node half entry exists
§4 dsh.client platform=web; inject target declared in harness workspace / local node_modules dsh.client(otherwise that edge will never reach the factory, FAIL); inject ↔ devDep type double insurance (WARN);dsh.client.external field type, self-reference (FAIL), baseline redundant line (WARN)
§5 client artifact existence,.cjs suffix, banner/footer contract;artifact bare require ↔ module table reconciliation(comment-aware scan: unknown specifier FAIL — module table cannot respond and will definitely throw; inlined safety layer externalized FAIL; bare builtin require WARN — must be manually confirmed to be within inliner feature detection);build config external ↔ platform baseline ∪ dsh.client.external reconciliation(out-of-bounds FAIL, externals declaration body not found WARN escalated to manual); external dead line (WARN)
§6 theme variables Perform declaration set reconciliation against var(--…) references (declaration sources: harness ui-theme/src/styles/*.css + plugin's own declarations): nonexistent DSH variable FAIL (fallback value would mask theme breakage); unused variables not reported
§7 Copy and locale Hardcoded CJK copy in JSX text/user-visible attributes FAIL; ordinary CJK string literal WARN;locales.ts(or locales/zh.ts+en.ts) zh/en key set parity FAIL
§8 Hygiene scoped package publishConfig.access, scripts.build/test
§9 Documentation version declarations Frozen 0.1.0-rc.x references and removed module dsh-client-runtime references (WARN) in current-state documentation (README/AGENTS/CLAUDE/docs, excluding CHANGELOG and acceptance evidence)

FAIL blocks. WARN and NOT_VERIFIED do not block, but the formal acceptance report must give a manual conclusion for each item.

§2 Fact layer (verified item by item against harness source code)

Review item Provenance method
Event name exists and semantics are correct packages/core/agent/src/runtime-types.ts(note:does not have agent/post-step)
slot name has actually been declared packages/client/ui-*/src grep in slots.inject(' / renderSlot('; slot'stype declarationin the owning client package, out-of-tree requires devDep (types) + dsh.client.inject(load order) double insurance
Tool API shape docs/cookbook/adding-a-tool.md + packages/core/tools/src/index.ts
lossless JSON validation packages/util/values/src/index.ts(walkJsonValue; old path packages/core/session/src/json.ts no longer exists)
Lifecycle/service ctx.get(optional) vs inject(hard dependency, if missing the entire plugin will not activate)

For the harness repository path and full index, see the development spec §Reference File Index. When verifying, use --harness-root the referenced repository as authoritative, and record its version and commit in the report.

§3 Contract layer (pitfalls actually hit in practice, check item by item)

  1. lossless JSON: any property value of a tool return value that is undefined is rejected (recursively)—deep-strip before returning.
  2. DSL restrictions:parameters does not support object-nested objects; standalone const schema literals must as const。
  3. client artifacts: the banner must be constructed var module = { exports: {} }; var exports = module.exports;;"type":"module" in-package cjs artifacts must outExtensions force .js; artifact bare require may only request platform baseline or dsh.client.external declared specifiers.
  4. client purity: non-baseline, non- dsh.client.external, non-inline safe-list @deepseek-ai/* value imports are forbidden (type-only is erased and not restricted)—the build purity gate will error out directly.
  5. Subprocess: long tasks async spawn + exec.signal;spawnSync freezes the entire harness.
  6. Explicit arguments: do not rely on the called CLI's silent defaults (a real case: contract-copilot's review_intensity default silently becomes "assertive").
  7. fail-loud: configuration errors throw inside apply; optional service defaults must explicitly state the degradation path.
  8. Exit code classification: domain results (partial/rejected) go into the canonical value without throwing; only infrastructure failures throw.
  9. Build pipeline: do not use pipes that swallow exit codes (cmd | grep | head && next once made a tsc failure silent, leaving a stale bundle on disk for hours).
  10. HMR boundary (historical conclusion, re-verify per version): in the 0.1.0-rc.7 era, bidirectional testing showed that neither half of an out-of-tree plugin hot-loads, and after an update dsh must be restarted; this conclusion has not been retested in later versions—treat it as a to-be-verified hypothesis during review (WARN semantics), and take the current harness's packages/client/hmr behavior actually measured as authoritative.
  11. Theme variables: only reference variables from the harness theme declaration set; fallback values (var(--x, #fff)) are only a last-resort display and cannot hide a broken dark-theme chain.
  12. Typed locale: product UI copy goes through the plugin's own namespace dictionary (zh is the key-set source of truth, en aligned), and components consume it via PropsLocale<'ns'> 's t() ; writing copy directly in JSX text/attributes is a violation.

§4 Documentation layer

The target plugin repository's CHANGELOG / DECISIONS / ROADMAP / ARCHITECTURE are in sync with this change; decisions are traceable (consecutive numbering, including retractions). Current-state docs must not retain expired version declarations (§1 §9 will provide a WARN list).

§5 Formal acceptance (candidate binding)

  1. git rev-parse HEAD record the candidate commit
  2. Clean profile install:dsh plugin --profile <验收名> add <路径> → --dump-config layered
  3. node half: boot without errors; tool successfully invoked for real in headless (full pipeline if an LLM is available, single-tool otherwise)
  4. client half (if any):__DSH_BOOT__ contains this package → /plugins/<id>/client.js downloadable → browser rendered screenshot(slot component actually appears)
  5. Evidence (commit + command output + screenshot) written into the acceptance report; missing any → NOT_VERIFIED

Standard browser forensics tool: ego-browser(agent browser, task space isolation, reuses local login state). For acceptance use ego-browser nodejs <<'EOF' ... EOF driver:gotoAndWait open local web UI → snapshotText/js perform DOM assertions (slot component exists, key content rendered) → captureScreenshot retain evidence. localhost testing requires no public network or extra login; faster than manual clicking and evidence is reviewable. When no ego-browser environment is available, accept manually and annotate the evidence source.

Output format

dsh-plugin-lint 报告 <目标> @ <commit>
harness 溯源: <DSH 版本> @ <harness commit>(解析来源)
§1 机械: [PASS|FAIL|WARN|NOT_VERIFIED...](脚本输出,退出码 = FAIL 数)
§2 事实: 每条引用 → 源码路径 → PASS/FAIL
§3 契约: 逐条 PASS/FAIL/NA
§4 文档: ...
§5 验收: PASS / NOT_VERIFIED(缺什么证据)
结论: 可发布 / 需修复(清单)/ 未验证

Known limitations

  • Regex-level parsing, no AST construction: complex patch structures, nested dictionaries, non-flat locale objects are handed off to manual review (for cases the script cannot parse it emits WARN/NOT_VERIFIED, not PASS)
  • Artifact bare builtin require can only prompt manual confirmation (the inliner's try/catch feature detection is legitimate; cannot be mechanically determined)
  • CJK detection in JSX text positions is heuristic (>…< interval contains CJK), does not include {} expression internals
  • The platform module table/purity regex/theme variable set/package manifest are all current facts read at runtime from --harness-root ; they are not distributed with this skill, nor is any version number preset
  • Does not automatically execute the target repository's build/test (reports the commands that should be run, to prevent accidental damage)