v0.5.1 — identity hardening + dev environment
SheetDiff v0.5.1 — identity hardening + a real dev environment
Two passes in one release: a fresh adversarial audit of v0.5's smart-identifier hierarchy (five real defects found and fixed), and a researched dev-environment overhaul based on how comparable open-source Next.js projects (cal.com, dub, formbricks, documenso, vitest, drizzle-orm) actually work in 2026.
Fixed — the audit pass
- Identity is now resolved once, on latest data, for every slice. The auto-detected key column was being re-detected per snapshot; when uniqueness flipped between them (two rows share a date on a baseline), the same row keyed differently over time and a compilation tab's baseline escaped ownership — deflating placed-since, the exact bug class v0.5 claimed to have killed.
- Dates no longer masquerade as row identifiers. A unique Date column used to outrank a real ID/SKU column in detection scoring (making a date correction look like remove+add), and the dedup's auto-tier keyed by date — two crew logs spanning the same period collapsed into one tab and vanished from billing. Date/week now score below real identifiers and are skipped by the dedup auto-tier entirely; a date key you pick deliberately is still honored.
sheetBillableNowhonors the per-tab key column — the sheet-page badge and the money page can no longer disagree, the invariant that function exists to guarantee.- A mostly-copy tab that owns real work is no longer skipped wholesale — the coverage-based compilation classification now caps strays at 2% of keyed rows (the real Line List sits at 1.9% and still classifies; 20-copies-plus-straggler no longer vanishes).
- Removals net out per tab again — the slice walk's key-namespace exception was inverted (within-tab repeats dropped, cross-tab repeats kept).
New — the dev environment
- Prettier with Tailwind class sorting and import organizing; the repo is formatted once and
npm run format/format:checkkeep it that way. - Pre-commit hooks (husky + lint-staged): ESLint --fix + Prettier on staged files only, skipped in CI.
- Coverage with teeth: vitest v8 coverage with enforced thresholds (currently ~80% lines), run in CI.
npm run verify: format + lint + typecheck + tests in one command — what CI checks, what you run before pushing.- Security workflows: CodeQL (weekly + PRs) and zizmor (lints our own Actions files).
- Hardened CI: least-privilege permissions, cancel-in-progress, timeouts,
persist-credentials: false, format + coverage steps. - Repo hygiene:
.nvmrc,.editorconfig,.vscodesettings + recommended extensions, PR template, feature-request form, FUNDING. - knip dead-code sweep — 6 unused scaffold components removed, and the phantom
google-auth-librarytype import is now derived fromgoogleapisitself.
367 tests green (6 new regression tests pin every audit fix). Node 22+.