DEV Community

Fernando Paladini
Fernando Paladini

Posted on

Your Repo Is L2 but Your Machine Is L4 — Harness Score 1.3 Adds Dual Scores and User-Scope Scanning

Your repository scan says L2 Guided. Your teammate runs the same command and gets L4 Self-correcting.

Neither of you is wrong. You have a lean repo harness — AGENTS.md, a few scoped rules, CI tests. They have the same repo plus a personal ~/.cursor/skills/ library, global Claude Code hooks, and Windsurf rules living under ~/.codeium/windsurf/.

Until now, harness-score could only answer one question: what is committed in git? That is the right question for CI gates and team maturity. It is the wrong question when you want to know what the agent on this laptop actually sees.

harness-score 1.3.0 introduces two scores — maturity and effective — plus .harness-score.json, --scope, and --gate. 1.3.1 (same week) extends --scope user to every multi-harness tool with documented global paths, including path aliases where tools store config outside the repo layout.

This article explains the split, shows how to configure it, and walks through what 1.3.1 added on top.


Prerequisites

  • Node.js 18+ (for npx)
  • Optional: a repo already scanned with harness-score (1.0 intro)
  • Optional: global harness files under ~/.cursor/, ~/.claude/, etc.

No code changes required in your repository — this is a scanner and reporting upgrade.


The problem: one score, two realities

Harness engineering wraps a coding agent with context, rules, hooks, tests, and guardrails. Teams gate CI on maturity levels L0–L4 because committed harness infrastructure is what everyone shares.

But developers also maintain personal harness layers:

  • Cursor skills and MCP config in ~/.cursor/
  • Claude Code skills and settings in ~/.claude/
  • Windsurf global rules under ~/.codeium/windsurf/ (not .windsurf/ in home)
  • Cline rules in ~/Documents/Cline/Rules/
  • Continue prompts in ~/.continue/

When the scanner only looked at the repo, two failure modes appeared:

  1. False pessimism locally — your machine runs a rich harness, but the report says L2 because nothing global counts.
  2. False optimism in CI — the repo looks fine, but every developer's personal overlay is doing the real work (and CI cannot see it).

1.3.0 separates these concerns instead of pretending they are the same number.


Two scores: maturity vs effective

Score What it includes Use for
maturity Repository files only CI gate (default), badge, team maturity
effective Repo ∪ user/system/extra scopes Local "what the agent sees on this machine"

When no extra scopes are enabled, both scores are identical. The JSON report always includes both blocks — stable schema, no surprises for tooling that parsed 1.2.0 output.

Set which score gates CI with gate:

{
  "scopes": { "user": false },
  "gate": "maturity"
}

Default stays conservative: CI gates on maturity unless you explicitly opt into gate: effective. Your team's official level remains repo-only.

Source: Metrics & Codes — scores.


Configuration surface (1.3.0)

.harness-score.json

Optional config at the scan root — strict schema, unknown keys error:

{
  "scopes": {
    "user": true,
    "system": false
  },
  "extraRoots": [
    { "id": "team-shared", "path": "../shared-harness" }
  ],
  "gate": "maturity"
}
Key Default Meaning
scopes.user false Include allowlisted user-level harness overlay
scopes.system false Include system-level overlay (minimal in v1)
extraRoots [] Extra harness trees merged into effective
gate "maturity" Which score --min-level compares

Precedence: CLI flags → Action inputs → config file → defaults.

CLI flags

# Repo-only maturity (unchanged default)
npx harness-score@1.3.1

# Include user-level harness in effective score
npx harness-score@1.3.1 --scope user

# Gate on effective instead of maturity (opt-in)
npx harness-score@1.3.1 --scope user --gate effective --min-level 3

# Custom config path
npx harness-score@1.3.1 --config ./ci/harness-score.json

JSON output now includes scopes, gate, and an effective block alongside maturity.

GitHub Action

- uses: paladini/harness-score/action@main
  with:
    min-level: '3'
    include-user-harness: 'true'
    gate: maturity

New outputs: effective-level, effective-percent — maturity outputs unchanged.


What --scope user actually scans (1.3.1)

1.3.0 shipped user-scope scanning for Cursor and Claude Code. 1.3.1 extends the allowlist to every multi-harness tool with documented global paths — with path aliases where tools store files outside the repo layout the checks expect.

Tool User-scope paths (examples) Notes
Cursor ~/.cursor/{skills,commands,agents,rules}, ~/.cursor/mcp.json IDE-only User Rules still invisible
Claude Code ~/.claude/{skills,commands,agents}, ~/.claude/settings.json, ~/.mcp.json
Windsurf ~/.codeium/windsurf/memories/global_rules.md.windsurf/rules/… Global rules live under Codeium
Cline ~/Documents/Cline/Rules/*.md.clinerules/… Fallback: ~/Cline/Rules
Continue ~/.continue/{rules,prompts}/ Inline rules in config.yaml not parsed (v1)
Codex / Antigravity ~/.agents/{skills,rules,workflows}/, ~/.codex/skills, ~/.gemini/rules/
OpenCode $XDG_CONFIG_HOME/opencode/agents/
Zed ~/.zed/commands/
GitHub Copilot Repo-only: .github/instructions/

Physical paths map to the same repo-relative shapes the harness registry uses — so checks behave like the files were in the repository.

Not scanned: arbitrary $HOME walks, Cursor User Rules stored only in the IDE UI, Continue inline rules embedded in config.yaml.

Full table: multi-harness — user-scope by tool.


Verify in 60 seconds

Scan repo-only (official team maturity):

npx harness-score@1.3.1 --json | jq '{maturity: .maturity.level, effective: .effective.level}'

Add user scope and compare:

npx harness-score@1.3.1 --scope user --json | jq '{maturity: .maturity, effective: .effective}'

If your global harness is richer than the repo, effective.level should be higher than maturity.level. If they match, your harness is fully committed — which is what CI wants.

Track progress over time (unchanged):

harness-score --json > baseline.json
# ... improve the harness ...
harness-score@1.3.1 --diff baseline.json

What did not change (and why that matters)

Surface Still true in 1.3.x
Check IDs (CTX-01HYG-08) Stable public API
Point totals / level thresholds Same 108-point ladder
Determinism No LLM · no network · no telemetry
Multi-harness OR semantics Cursor, Claude Code, Windsurf, Cline, Continue, Codex, Copilot, …
Default CI behavior gate: maturity, no user scope — identical to 1.2.0

1.3 is a minor + patch: new reporting dimensions, opt-in scopes. Teams gating CI on L3 without --scope user see the same maturity score they saw on 1.2.0.


Honest limits

  • Copilot has no global path — keep team instructions in .github/instructions/ for parity.
  • Continue inline rules in config.yaml are not parsed yet.
  • Cursor User Rules in the IDE UI remain invisible (not on disk).
  • Effective score is machine-local — do not gate production CI on it unless you intentionally want personal overlays to count.

How this fits the release series

Version Headline Type
1.0.0 Stable API, multi-harness OR semantics Major
1.1.0 EN / pt-BR / es guide + HKS-05 fix Minor
1.2.0 zh-CN / hi-IN guide Minor (docs)
1.3.0 Dual maturity/effective scores, scopes, config Minor
1.3.1 User scope for all multi-harness tools Patch

Each release expands what you can measure without moving the maturity goalposts for teams that never opt in.


Try it

npx harness-score@1.3.1 --scope user

Links:


Takeaway

A single maturity number could not honestly describe both what the team commits and what the agent on your laptop loads. 1.3.0 splits them. 1.3.1 makes the user-scope overlay useful across the full multi-harness surface — including the weird paths where Windsurf and Cline actually store globals.

Run --scope user once locally. If effective beats maturity by a full level, your personal harness is carrying the repo. That is not a failure — it is signal about where to commit next.

What is your maturity vs effective delta — and which tool's global paths surprised you? Drop both in the comments.

Top comments (0)