Files
agentic-dev/package.json
Danijel Martinek 412d994733 feat(coverage): pnpm coverage:diff script + L1 implementation
Lands L1 of the agent-first coverage architecture (ADR-020) — the
cover-the-diff gate. Reads a merged lcov + git diff against a base
ref, asserts every changed *executable* line was exercised.

Script: scripts/coverage/diff.mjs (zero-dep Node ESM)
  - parseLcov: SF -> Map<line, count>; only DA records read
  - parseGitDiff: parses --unified=0 output into Map<file, Set<line>>
  - computeDiffCoverage: cross-references both, emits result tree
  - Allowlist of paths that don't gate (tests, configs, docs, .sh,
    DI bootstrap, interfaces, CMS, factories, contracts, UI)
  - Path matching handles three lcov path conventions: absolute,
    repo-relative, and per-package relative
  - CLI flags: --base (default origin/main), --lcov (default
    coverage/lcov.info), --json (suppress stderr summary)
  - stdout: machine-readable JSON for the dispatch loop
  - stderr: human summary
  - Exit 0 on pass, 1 on fail or error

Test surface: scripts/coverage/diff.test.mjs (14 tests, all green)
  - Fixtures at scripts/coverage/__fixtures__/{sample.lcov,sample-diff.patch}
  - Covers: lcov parsing, diff parsing, pass path, uncovered lines,
    non-executable line skipping, no-coverage-data detection,
    allowlist filtering, end-to-end mixed case, path matching

Wired:
  - root package.json adds "coverage:diff" script
  - .gitignore anchored so per-package coverage/ stays ignored but
    scripts/coverage/ stays tracked

Smoke-tested end-to-end against packages/auth/coverage/lcov.info —
correctly skips shell scripts + manifest files (via allowlist + path
suffix match), correctly flags files not present in the per-package
lcov (which is expected; full repo coverage needs the L2 aggregate
that the next story lands).

CI integration deferred to the L2 aggregate story (the merged
coverage/lcov.info this script reads doesn't exist yet — pnpm
coverage:aggregate produces it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:04:09 +02:00

47 lines
1.5 KiB
JSON

{
"name": "template",
"private": true,
"packageManager": "pnpm@9.15.4",
"engines": {
"node": ">=20"
},
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test",
"test:e2e": "turbo run test:e2e",
"test:stories": "turbo run test:stories",
"test:visual": "pnpm --filter @repo/storybook exec concurrently -k -s first -n 'SB,VRT' -c 'magenta,blue' 'pnpm --filter @repo/storybook exec http-server storybook-static --port 6006 --silent' 'pnpm --filter @repo/storybook exec wait-on tcp:6006 && pnpm exec playwright test'",
"typecheck": "turbo run typecheck",
"conformance": "node scripts/conformance.mjs",
"coverage:diff": "node scripts/coverage/diff.mjs",
"fallow": "fallow",
"fallow:audit": "fallow audit --base main",
"work": "node scripts/work/cli.mjs",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"",
"prepare": "husky"
},
"devDependencies": {
"@ai-hero/sandcastle": "*",
"@playwright/test": "^1.49.0",
"@turbo/gen": "^2.4.0",
"@types/node": "^22.0.0",
"fallow": "^2.73.0",
"husky": "^9.0.0",
"lint-staged": "^16.0.0",
"prettier": "^3.5.0",
"turbo": "^2.4.0",
"typescript": "^5.8.0"
},
"lint-staged": {
"*.{ts,tsx,js,mjs,jsx}": [
"eslint --fix --max-warnings=0 --no-warn-ignored"
],
"*.{ts,tsx,js,mjs,jsx,json,md,yml,yaml}": [
"prettier --write"
]
}
}