"Coverage measurement and ratchet"
TASK-IMP-012: Coverage measurement and ratchet
Summary
CyberOS 1.x needs a coverage ratchet for the install/docs-tools surface — not a monorepo-wide cargo llvm-cov. This task lands a deterministic install-suite coverage metric, a committed baseline, and a ratchet that fails only when coverage regresses.
Problem
coverage-scope.mjs maps a task diff to per-file coverage for authoring, but nothing ratchets the install suite itself. Autodetected COVERAGE_CMD may claim cargo llvm-cov on this monorepo even when the payload work under test is shell/Node. Without a baseline, coverage gates either do nothing useful or fail on absolute thresholds that are wrong for shell tooling.
Proposed Solution
Add tools/install/docs-tools/coverage-ratchet.mjs that measures install-script test-touch coverage: the fraction of tools/install scripts (.sh / .mjs under gates/, docs-tools/, and top-level, excluding tests/) whose basename is referenced by at least one file under tools/install/tests/. Compare against committed tools/install/coverage-baseline.json. Exit non-zero only when current pct is strictly below baseline pct. --write-baseline updates the baseline after a measured improvement. Vendor the tool via build.sh.
Alternatives Considered
- Wire cargo llvm-cov as the ratchet. Rejected: mission scopes 1.x away from platform-wide llvm-cov.
- Absolute 90% threshold only. Rejected: shell suites rarely have line instrumentation; ratchet-from-baseline is the honest floor.
- Extend coverage-scope.mjs in place. Rejected: scope tool is task-diff oriented; ratchet is suite-floor oriented. Keep companions, share docs-tools home.
Success Metrics
- Primary: ratchet fails on constructed regression, passes at baseline,
--write-baselineraises floor. - Guardrail:
run_all.shstays green; missing baseline fails closed (exit 2) rather than inventing 0.
Scope
In scope: coverage-ratchet.mjs, coverage-baseline.json, tests, build.sh vendor line, CHANGELOG.
Out of scope / Non-Goals
- Instrumenting bash with kcov/c8.
- Replacing COVERAGE_CMD autodetect for consumer repos.
- Changing coverage-scope.mjs CLI contract.
Dependencies
None. Soft companion: coverage-scope.mjs (IMP-098) remains the per-task authoring tool.
AI Authorship Disclosure
- Tools used: Cursor agent, batch/12c.
- Human review: session operator Stephen Cheng.
§1 - Description (normative)
coverage-ratchet.mjsMUST compute install-suite test-touch coverage over the closed path set:tools/install/*.{sh,mjs},tools/install/gates/*.{sh,mjs},tools/install/docs-tools/*.{sh,mjs}(files only;tests/excluded).- A script counts as covered when its basename appears as a substring in any
tools/install/tests/test_*.sh(or othertest_*file under that directory). - Output MUST include schema
coverage-ratchet@1,pct(one decimal),covered,total, and sorted uncovered basenames. - Default mode MUST compare
pcttotools/install/coverage-baseline.json(or--baseline <path>). If baseline missing → exit 2. Ifpct < baseline.pct→ exit 1 (regression). Ifpct >= baseline.pct→ exit 0. --write-baselineMUST rewrite the baseline file from the current measurement and exit 0 (does not require prior baseline).--jsonMUST print the measurement object to stdout; human summary may go to stderr.build.shMUST vendorcoverage-ratchet.mjsinto the payloaddocs-tools/when present.- Suite
tools/install/tests/test_coverage_ratchet.shMUST cover regression / pass / write-baseline / missing-baseline.
Acceptance criteria
- [x] AC1: Measurement against a fixture with known covered/uncovered counts matches expected pct. (t01)
- [x] AC2: pct below baseline → exit 1. (t02)
- [x] AC3: pct equal or above baseline → exit 0. (t03)
- [x] AC4: missing baseline → exit 2. (t04)
- [x] AC5:
--write-baselinecreates/updates baseline to current pct. (t05) - [x] AC6: payload build copies coverage-ratchet.mjs. (t06)
Test plan
bash tools/install/tests/test_coverage_ratchet.sh
Audit
TASK-IMP-012 audit
Honest 1.x scope: install-suite test-touch ratchet, not cargo llvm-cov. Baseline fail-closed, regression-only fail, explicit --write-baseline. Companion to coverage-scope (IMP-098) without breaking its CLI. ACs map 1:1 to suite scenarios.
SUMMARY verdict: pass issues_open: 0 next_action: none