# Contributing ## Before a change Run the full check. It needs Node.js 22 and no dependencies: ```bash node scripts/validate-packages.mjs node scripts/pack-dry-run.mjs ``` `validate-packages.mjs` imports each real plugin entry and asserts the skill it registers, so a package that looks structurally correct but fails to load is caught before review. ## The rules that are not negotiable **One lane, one skill, one job.** The root bundle registers the lanes; a lane registers exactly one skill. If a change makes a lane register a second skill, it is a fourth lane, not a bigger third one. If a change blurs two lanes into each other, it belongs in neither. **The root manifest stays a valid bundle.** DSH Hub submits one repository as one plugin and validates the root `package.json`, so the root must keep `dsh.bundle.patch`, stay publishable (never `private`), and keep `packages/` in `files`. The validator asserts all of this, plus that the root actually registers the three lanes when applied and fails closed on an unknown `config.lanes` entry. **No lifecycle scripts, ever.** `preinstall`, `install`, `postinstall`, `prepare`, and `prepublish` run on the user's host, not in the agent sandbox. This bundle ships prebuilt — there is nothing to compile — and the validator fails if one appears. **Never claim an upstream collector ran.** These packages carry Better Harness's evidence boundaries as prompt text. They contain no collectors and must not be worded as if they produce final severities or repository-wide scores. When evidence is unavailable, the skill reports that boundary — it does not invent a finding. **Keep `dependencies` empty.** Zero runtime dependencies is a feature, not an accident: it is what keeps the install auditable — what is in the tarball is what runs. A change that adds a runtime dependency needs to justify itself against that. **`parseCanonicalSkill` stays duplicated.** The copies in each package are intentional — see [`docs/specs/2026-08-20-dsh-plugin-extraction.md`](docs/specs/2026-08-20-dsh-plugin-extraction.md). Do not extract it into a shared runtime dependency. Change all copies together; the validator asserts they agree. ## Skill text Skill frontmatter must stay inside the portable contract: a `name` matching the directory, and a `description` of at most 500 characters that says both when to use the skill **and when not to**. The three lanes are deliberately adjacent, so the negative clause is what stops a session question from pulling in the asset auditor — treat it as load-bearing, not boilerplate. Keep the body short and put schemas, rejection rules, and long tables in `references/`. ## Scope This repository is the Better Harness port and nothing else. Plugins with a different origin belong in their own repository, even when they target the same harness. ## Compatibility The tested baseline is DSH `0.1.0-rc.6`, declared in every package's `peerDependencies`. If you validate against a newer DSH, update the baseline in the same commit as the evidence. ## Publishing Publication is deliberately not automated. Registry credentials, package ownership, and release tags are external actions the maintainer performs by hand.