Pular para o conteúdo principal
V

dsh-skill-audit

vamyane/dsh-skill-audit

Skill and plugin audit console for DeepSeek Harness. It scans local skill folders and installed DSH plugins, checks the packaging rules that commonly break installation, scores each asset, and exports a Markdown fix report.

Instalar

dsh plugin --profile web add github:vamyane/dsh-skill-audit

README

dsh-skill-audit

Skill and plugin audit console for DeepSeek Harness. Two modes in one panel:

  1. DSH assets — scan local DSH skills and plugins, score each asset 0-100 (S/A/B/C/D), list every pass/warn/fail check with a fix hint, export a Markdown report.
  2. WorkBuddy package — audit a WorkBuddy skill package or expert package (directory or .zip) with the 25 gate checks (G01–G19 / E01–E06), a quality score Q (5 dimensions, 22 items), a value score V (6 dimensions), automatic V calibration (V_final = min(V_raw, Q + 15)) and a suggested price band.

dsh-skill-audit is a DSH plugin (dsh.bundle + a browser half): it mounts a 🛡️ Audit button in the left sidebar and a full-screen React panel (no iframe). The host half does the scanning and serves the JSON routes.

What it scans

DSH mode

SourceWhat is picked up
~/.dsh/skills/*every skill directory (SKILL.md)
<profile>/node_modules/*installed packages whose package.json declares dsh.bundle (scoped packages included)
<workspace>/dsh-plugins/*plugins under development in the current workspace

WorkBuddy mode

InputDetection
directory or .zipskill package when SKILL.md is at the package root (a single wrapper top directory is auto-unwrapped and then flagged by G01)
directory or .zipexpert package when .codebuddy-plugin/plugin.json exists (a ZIP must have one top directory equal to the package name)

ZIPs are read in pure JS: the central directory is parsed and entries are inflated with zlib.inflateRawSync (stored + deflate). Nothing is written to disk unless script syntax checking needs a temporary copy of the scripts — that temp directory is removed immediately afterwards. ZIP64 and encrypted archives are not supported.

DSH mode checks

Skills (SKILL.md based)

CheckWeightWhat is verified
SKILL.md20file exists and is not empty
frontmatter description20YAML frontmatter present, description present and substantial
frontmatter author10author declared
frontmatter name10matches the directory name
LICENSE10license file (or a license declared in frontmatter)
sensitive info20obvious keys / tokens / private keys (values are redacted)
local paths / privacy10hard-coded home directories such as a full user path

Plugins (package.json based)

CheckWeightWhat is verified
package.json5readable, valid, name matches the directory
dsh.bundle15declared, patch file exists
cordis.patch.yml row name15the inserted row's name equals the package name
client module id10__ModuleLoader__.load({ id }) equals the package name
host module name10export const name / exports.name equals the package name
README5at least one README
bilingual README5README.md plus README.zh.md / README.en.md
LICENSE7license file exists
icon10icon is a 512x512 PNG (dimensions read from the PNG header)
files whitelist5covers lib/app/assets/README*/LICENSE/cordis.patch.yml
sensitive info10obvious keys / tokens / private keys (values are redacted)
local paths / privacy3hard-coded home directories

DSH score = weighted pass ratio (pass = 1, warn = 0.5, fail = 0, skip not scored). Grades: S ≥ 90, A ≥ 80, B ≥ 70, C ≥ 60, D < 60.

WorkBuddy mode checks

25 gate checks, ported from skill-value-auditor/rubric/rubric.v1.json (rubric v1.0.1). Every check returns pass / warn / fail / skip with a severity (blocker / major / minor), a readable reason, evidence, and the rubric's fix hint.

IDSeverityCheck
G01blockerpackage structure (flat ZIP, SKILL.md at root, depth ≤ 2, no junk files; expert ZIP top dir = package name)
G02blockerSKILL.md frontmatter required fields (name/description/version; for expert-embedded skills name/description)
G03majorname equals package name and is kebab-case
G04blockerdisplay-name rules (≤ 15 chars, only Chinese/English/digits/-/—, no brackets or spaces)
G05blockerfiles referenced in backticks inside docs must exist (wildcards are rejected)
G06blockerno hard-coded keys / tokens / private keys (values redacted)
G07blockerYAML frontmatter parses (including the ': ' quote trap)
G08blockerpaid package legal files: LICENSE-USE / NOTICE / PRIVACY / SECURITY / CHANGELOG + a disclaimer
G09minoricon asset is a 512x512 PNG ≤ 500 KB
G10majorbilingual fields (description_en, display_name_en, examples_en)
G11blockerscript syntax compiles (node --check for JS, Python ast.parse when a Python interpreter is available)
G12blockerno destructive / over-privileged commands (rm -rf /, registry, browser credentials …)
G13majorno absolute promises (保本 / 稳赚 / 零风险 / 包过 / 避税 …)
G14majorno unfinished placeholders (TODO / 待补 / TBD …)
G15minorUTF-8 without BOM
G16blockerno data exfiltration (upload / webhook patterns)
G17majorpackage size < 3 MB (expert packages < 10 MB)
G18majorauthor field
G19blockerexamples_zh / examples_en each ≤ 3 entries (platform parse limit)
E01blockerplugin.json has all 16 required fields and they are valid
E02blockeravatar is 512x512 and ≤ 500 KB
E03blockertags = 3, quickPrompts = 3, defaultInitPrompt aligned, profession non-empty
E04majordisplayDescription.zh is 40–50 characters
E05blockeragents/*.md frontmatter matches agentName (name/description/displayName/profession/maxTurns, no tools)
E06blockerTeam-type settings.json / teamInfo consistency

Quality Q (0–100, five dimensions)

DimensionWeightWhat it looks at
Q1 structural / engineering robustness18gate result, script presence and static syntax, self-check, version/changelog/size/encoding
Q2 triggering and routing14description coverage of example questions, generic words, name searchability, example quality
Q3 workflow executability24numbered steps and branches, input collection + graceful degradation, output templates, uncertainty boundaries
Q4 knowledge quality26knowledge density, static consistency, dates/sources, disclaimers, reusable assets
Q5 experience / commercial basics18first-run deliverable, bilingual listing copy, export formats, token efficiency

Each of the 22 items is scored on a 0–4 anchor scale, scaled to its max, and every item carries evidence (counts, files, matched words). The report prints all of it.

Value V (0–100, six dimensions) and pricing

DimensionWeightBasis
V1 demand strength25domain demand prior + loss/event/frequency/decision/search word density
V2 delivery certainty20tables, scripts, templates, acceptance criteria
V3 result value20domain loss baseline + money / fine / claim words
V4 moat / substitutability15knowledge size, tables, scripts, formulas, compliance hooks, minus generic words
V5 reuse frequency10domain frequency prior + periodic vs one-time words
V6 willingness to pay / risk10domain, disclaimer presence, compliance signals

Calibration: V_final = min(V_raw, Q + 15) — a package cannot be "valuable" if its delivery is weak. Price bands (by V_final): S ≥ 85 → ¥49–79 or subscription; A ≥ 72 → ¥29.9; B ≥ 60 → ¥19.9; C ≥ 48 → ¥9.9; otherwise free / do not list. If V5 ≥ 80 and V ≥ 70 a monthly subscription (¥9.9–19.9/month) is suggested. Gate blockers force V_final = 0 and no pricing.

Penalties (P1–P6) are applied as cross-dimension deductions and listed separately: duplicate lines > 30 %, missing disclaimer in a professional domain, absolute claims, sibling similarity (needs a batch corpus, reported as not triggered), oversized package/text, placeholders.

Using the panel

  1. Install the plugin (plugin market, or drop it into the profile and add its bundle row).
  2. Click 🛡️ Audit at the bottom of the left sidebar.
  3. DSH assets tab: scans on open, ↻ Rescan, expandable rows, filter tabs, ⬇ Export report → <workspace>/outputs/skill-audit-<YYYY-MM-DD>.md.
  4. WorkBuddy tab: paste an absolute path to a package directory or .zip, click 🔍 Scan package; the panel shows the gate table grouped by severity, Q dimensions, V dimensions, penalties and the price band. ⬇ Export report → <workspace>/outputs/wb-audit-<name>-<YYYY-MM-DD>.md.
  5. Static preview opens the bundled app/panel.html preview page in a new tab (design reference only, sample data).

Host routes

RouteMethodDescription
/api/dsh-skill-audit/scanGETDSH scan JSON; optional ?workspace=<absolute path> hint
/api/dsh-skill-audit/reportPOSTDSH scan + Markdown report; optional body { "workspace": "<absolute path>" }
/api/dsh-skill-audit/wb-scanPOSTWorkBuddy package scan; body { "path": "<absolute path>", "paid"?: true/false, "skipScripts"?: true }
/api/dsh-skill-audit/wb-reportPOSTWorkBuddy scan + Markdown report; body { "path": "...", "workspace"?: "..." }

All routes sit on the shared /api channel of the host connection service, so login and origin checks are handled by DSH. WorkBuddy scans are read-only; the only writes are the exported reports under <workspace>/outputs/.

Which workspace?

The report is exported to, and <workspace>/dsh-plugins/* is scanned from, the first valid candidate:

  1. the current session working directory reported by the panel (most accurate),
  2. the DSH_WORKSPACE environment variable,
  3. workspace in ~/.dsh/skill-audit.config.json,
  4. the host process process.cwd().
// ~/.dsh/skill-audit.config.json
{ "workspace": "C:/path/to/your/workspace" }

Only an existing, non-root absolute directory is accepted; everything else silently falls back.

CLI

The same audit logic runs without DSH:

# DSH assets
node tools/scan.mjs                          # scan the machine, workspace = cwd
node tools/scan.mjs --workspace .            # specify the workspace
node tools/scan.mjs --asset ~/.dsh/skills/ai-brain   # audit one DSH asset
node tools/scan.mjs --json                   # machine-readable output
node tools/scan.mjs --report report.md       # also write a Markdown report

# WorkBuddy packages
node tools/scan.mjs --wb E:/skills/release/my-skill-1.0.0.zip
node tools/scan.mjs --wb E:/workspace/my-expert --json
node tools/scan.mjs --wb <path> --paid       # force paid-package legal checks
node tools/scan.mjs --wb <path> --skip-scripts   # skip static script syntax checks
node tools/scan.mjs --wb <path> --report wb-report.md

--wb exits with code 1 when the package has gate blockers, 0 otherwise (useful in CI).

Development

node build.mjs          # gzip app/panel.html into lib/client.js
node test/smoke.mjs     # offline smoke: gzip payload, slots, both panel modes, host routes
node test/scan.test.mjs # DSH mode fixtures + route integration
node test/wb.test.mjs   # WorkBuddy fixtures (good/bad skill & expert, dir + zip) + Q/V + routes
npm test                # all three
npm pack --dry-run      # inspect the published file set

Layout:

lib/index.js            host half (4 routes, cordis plugin entry)
lib/audit.mjs           DSH scan / score / Markdown logic
lib/wb-package.mjs      WorkBuddy package reader (ZIP central directory, dir view, YAML subset)
lib/wb-audit.mjs        WorkBuddy gate checks + Q/V + pricing + Markdown report
lib/client.template.js  browser half template (React panel, two slots, two modes)
lib/client.js           generated by build.mjs (do not edit)
app/panel.html          static preview page, gzipped into lib/client.js
tools/scan.mjs          CLI (DSH + WorkBuddy)
tools/make-icon.py      generates assets/icon.png with Pillow
test/                   smoke + DSH scan tests + WorkBuddy tests

Privacy and safety

  • Scans are read-only: they never modify the scanned skills/plugins/packages, and they make no network calls.
  • The only writes are the exported reports under <workspace>/outputs/ (plus a temporary copy of package scripts while node --check / Python AST runs, removed immediately).
  • Secret matches are reported as a type and a count only; the matched value is never copied into the JSON or the Markdown report.
  • Local paths are reported as a count; usernames are not echoed back.
  • Everything stays on this machine and is only shown to the local DSH panel.

Known limitations

  • WorkBuddy scoring is a heuristic static approximation, not a model or a human reviewer: gate checks are deterministic, Q/V use word/structure heuristics. Every score in the report carries its evidence so it can be audited, but treat Q/V as guidance, not truth.
  • YAML parsing is a small subset parser (scalars, block scalars, lists, simple nested maps) — unusual YAML may be rejected or under-read.
  • G11 only checks static syntax (node --check, Python ast.parse); scripts are not executed, so --demo / selfcheck exit codes / T1 sandbox runs are not verified.
  • T3 sibling-package similarity and T4 behaviour scoring are not automated (they need a batch corpus and real agent output); P4 is reported as not triggered.
  • DSH icon validation only understands PNG headers; SVG/JPG icons get a warning.
  • Report file names are date-based, so two exports on the same day overwrite each other.
  • WorkBuddy ZIP support covers stored/deflate, no ZIP64/encryption; packages must be readable by the DSH host process (absolute path).
  • Paid-package detection is heuristic (legal files / price fields / --paid); it may miss a paid package that ships no legal files.
  • In a browser host where the session list is unavailable, workspace detection falls back to environment/config/cwd as described above.

License

MIT. See LICENSE.

Plugins relacionados