Skip to content

Latest commit

 

History

History
145 lines (120 loc) · 7.03 KB

File metadata and controls

145 lines (120 loc) · 7.03 KB

Contributing to Harness Score

Thanks for considering a contribution — issues, pull requests, and discussion are all welcome. This project is small enough that a short read here should be all you need before opening a PR.

Ways to contribute

  • Report a false positive/negative. The scanner is deterministic pattern matching; it will occasionally misjudge a real repository (a linter it doesn't recognize, a rule format it doesn't parse). These reports are the most valuable contribution there is — see tech-leads-club/fakeflix in our own history for an example of a real-world test that shipped several fixes.
  • Propose or add a check. New tools, new conventions, new artifacts worth rewarding. See ROADMAP.md for what's already planned.
  • Improve the guide. Docs fixes, clearer recipes, better examples.
  • Fix a bug in the CLI, the plugin, or the GitHub Action.

Open an issue before a large PR (a new check, a check change) so we can agree on the approach first — check changes touch multiple files that must stay in sync (see below) and are easiest to get right with agreement up front. Small fixes (typos, docs, obvious bugs) can go straight to a PR.

Project layout

packages/cli/    the scanner — TypeScript, ESM, zero runtime dependencies
  src/checks/    one file per dimension
  src/score.ts   the maturity model (levels L0–L4)
  test/          vitest; fixtures/level-0..4 pin each maturity level
docs/            the VitePress guide (deploys to GitHub Pages)
plugins/         one directory per editor/agent (cursor/, claude-code/, …),
                 plus shared/ (see PLUGINS-ROADMAP.md)
action/          the composite GitHub Action wrapping the CLI

Full conventions — written for agents, equally useful for humans — live in AGENTS.md. Read it before touching packages/cli.

The three invariants that matter most

  1. The CLI stays deterministic. No LLM calls, no network, no telemetry, no Date.now()-dependent output. Filesystem reads and parsing only — a PR that breaks this will be asked to change approach.
  2. Zero runtime dependencies in packages/cli. Fast npx, no supply chain surface. Dev dependencies are fine.
  3. The maturity model lives in three places that must change together: packages/cli/src/score.ts (implementation), docs/guide/maturity-model.md (levels), docs/guide/measure-and-improve.md (check catalog). A docs-sync test enforces that check IDs, points, and anchors match across all three — npm test will fail loudly if you update one and not the others.

Check IDs (CTX-01, SNS-03, …) are public API: never renumber or reuse one, even if a check is removed.

.github/CODEOWNERS auto-requests review on PRs touching checks, the maturity model, the maturity docs, fixtures, or the release workflow — not a gate, just a heads-up on the highest-stakes paths in the repo.

Adding or changing a check

This is the highest-value contribution and the one most likely to need a design discussion first, because it changes what every existing repository scores:

  1. Open an issue using the Check change template, describing the artifact you want to detect and why it deserves points (or why an existing check's points/logic should change, or why a check should be removed).
  2. Implement the check in the relevant packages/cli/src/checks/*.ts, wire it into the dimension total, and add/update fixtures under fixtures/level-0..4/ so the maturity ladder still makes sense at every level.
  3. Update docs/guide/maturity-model.md and docs/guide/measure-and-improve.md in the same PR — packages/cli/test/docs.test.ts and packages/cli/test/maturity-sync.test.ts enforce that check IDs, points, dimension totals, and level thresholds all stay in sync across score.ts and both docs pages; npm test fails loudly otherwise.
  4. Run the full gate before opening the PR (see below).

Proposing a preset

.harness-score.json's extends key applies named, maintainer-curated presets — bundles of per-check severity overrides (see Team customization in the guide). This is deliberately not a free-form per-repo opt-out: presets go through the same review that protects the check catalog, so a badge that says "L3 under preset X" still means something comparable across every repo that adopts X.

  1. Open an issue (the Check change template is close enough — describe which checks the preset would set to "off" and why the exclusion is structural, not a preference: a policy constraint, not "we don't feel like it"). Presets that reduce a whole dimension to zero applicable checks are the highest-scrutiny case, since they can cap the maturity ladder (see below).
  2. Add the preset to PRESET_REGISTRY in packages/cli/src/config.ts. Derive its severity map from ALL_CHECKS where possible (filter by dimension or check ID) instead of hardcoding IDs, so it never drifts as the catalog changes.
  3. If the preset excludes every check in a dimension that a LEVEL_REQUIREMENTS entry depends on (dimAtLeast in score.ts), the affected level becomes unreachable under that preset — computeLevel reports this as capped with a capReason, not as a silent pass. That's expected, not a bug to work around: don't add special-casing to let a preset "skip" a ladder requirement it structurally can't satisfy.
  4. Document the preset in docs/guide/metrics-and-codes.md's "Built-in presets" table with a {#preset-<name>} anchor matching the preset's key — packages/cli/test/docs.test.ts asserts every PRESET_REGISTRY key has one. Mirror the section in docs/pt-BR/guide/metrics-and-codes.md too.
  5. Add tests: severity resolution in packages/cli/test/config.test.ts, and — if the preset can cap a level — a capped/capReason assertion in packages/cli/test/score.test.ts or scoring-integration.test.ts.

Before opening a PR

npm install
npm test            # build + vitest — must pass
npm run lint         # biome — lints and checks formatting
npm run scan         # self-audit — this repo must stay at L4
npm run docs:build   # builds the guide — dead links fail it

CI runs the same checks; a red run will block review.

If your change is user-facing (a new/changed check, a CLI flag, a bug fix a user would notice), add a changeset: npm run changeset, pick a bump type, and describe the change — it becomes an entry in packages/cli/CHANGELOG.md the next time a maintainer runs the release process. Skip it for docs-only/internal changes.

Releasing

Releases (versioning, publishing to npm/GitHub Packages/JSR, docs deploy) are handled by a maintainer — see RELEASING.md if you're picking that up.

Code of conduct

Participation in this project is governed by our Code of Conduct.