Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ observations, not commitments or a service-level guarantee — reviews happen wh
**One-shot, merge-ready as-is.** We do not request changes or iterate on contributor PRs — a PR is
merged exactly as it stands or it is closed; there is no "changes requested" back-and-forth. Before CI
we rebase your branch onto `main` with a **merge commit**, then review **after** CI completes — so a
rebase conflict, or any red CI (including **~97% patch coverage, branch-counted, enforced by Codecov**),
rebase conflict, or any red CI (including **~99% patch coverage, branch-counted, enforced by Codecov**),
closes the PR. Recover by opening a **fresh, corrected PR**. PRs touching guarded paths (CI config, the
review engine, migrations, and similar — the set varies) are held for manual review rather than
auto-acted.
Expand Down Expand Up @@ -157,7 +157,7 @@ npm audit --audit-level=moderate
```

`npm run test:ci` runs the normal combined gate. The coverage requirement is **patch coverage**:
every line your PR adds or changes must be **97%+ covered** (statements, branches, functions, lines).
every line your PR adds or changes must be **99%+ covered** (statements, branches, functions, lines).
This is enforced by Codecov's `codecov/patch` status check, which looks only at your diff — so it
depends solely on your own changes and is unaffected by what else merges. Run `npm run test:coverage`
locally when you change behavior and make sure your new branches, fallback paths, and sanitizer rules
Expand Down
10 changes: 10 additions & 0 deletions test/unit/codecov-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ describe("Codecov policy", () => {
expect(project.informational).toBe(true);
});

it("keeps CONTRIBUTING patch-coverage guidance aligned with codecov.yml", () => {
const contributing = readFileSync("CONTRIBUTING.md", "utf8");
const patchTarget = nestedRecord(readYaml("codecov.yml"), ["coverage", "status", "patch", "default"]).target;
expect(patchTarget).toBe("99%");
expect(contributing).toMatch(/~99% patch coverage/i);
expect(contributing).toMatch(/99%\+ covered/i);
expect(contributing).not.toMatch(/~97% patch coverage/i);
expect(contributing).not.toMatch(/\b97%\+ covered/i);
});

it("fails closed when the backend coverage report is missing or cannot upload", () => {
const workflow = readYaml(".github/workflows/ci.yml");
const validateCode = nestedRecord(workflow, ["jobs", "validate-code"]);
Expand Down