mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
Land every file the day view, the timeline and life events share before any of them is built, so the server, the day view and the timeline can be built side by side without editing the same file (#613). Schema and migration 0387: LifeEvent with a short category list, calendar start and end dates, a day/month/year precision, encrypted title and note, a soft-delete tombstone and an index for the per-user live list. Every new column is annotated for the column-reader sweep. Life events travel in both backup purposes with their two ends in one file, are wiped with the account, and are registered for key rotation. src/lib/day/contract.ts carries the constants and wire types for GET /api/day/{date}, /api/day/index, /api/timeline, /api/timeline/readiness and the life-event routes, free of Zod so the navigation chrome can import it; the schemas beside it feed the routes and the published contract. The Coach and MCP tool name get_day is reserved there, and life events are listed as the one section no model ever sees. The opt-in timeline module, its navigation entry, the day-section and timeline-lane surfaces, the day and timeline query keys (evicted by every record data bundle), and stub routes that answer 501 behind their admissions. The four cross-section reads declare the whole record for now; the life-event list is a profile read, and life events join the profile sharing domain and its consent copy in all seven locales. The day, timeline and lifeEvents message namespaces carry their base copy as release-pending keys. The aggregate bundle cap moves to 4400: the branch already measured 4365 against 4335, and the new copy adds 10 KB.
183 lines
7.8 KiB
JSON
183 lines
7.8 KiB
JSON
// Dead-code configuration. JSONC rather than JSON so this can say what the
|
|
// gate proves — the previous JSON file could not, and the difference matters
|
|
// more here than anywhere else in the repo.
|
|
//
|
|
// ## What `pnpm knip` (the CI gate in .github/workflows/knip.yml) proves
|
|
//
|
|
// A module, export or dependency that nothing in the repository reaches is a
|
|
// build failure. That is a real property and it catches the ordinary case: a
|
|
// helper left behind after its last caller was rewritten.
|
|
//
|
|
// ## What it does NOT prove, demonstrated
|
|
//
|
|
// It does not prove a module is still reachable from production. Vitest is a
|
|
// knip plugin here, so `src/**/__tests__/**` are entry files, and a module
|
|
// whose ONLY importer is its own test counts as used — forever. Planting
|
|
// `src/lib/dead-probe.ts` with a single test importing it left `pnpm knip` at
|
|
// exit 0. Nothing in the default pass can see that class of dead code, so do
|
|
// not read a green Dead-code gate as "every module is still wired to
|
|
// something that ships".
|
|
//
|
|
// ## The pass that does see it
|
|
//
|
|
// pnpm knip --production --include files
|
|
//
|
|
// Production mode drops the plugin-supplied test entries and keeps only the
|
|
// entry and project patterns suffixed with `!` below — the app router tree,
|
|
// the proxy, instrumentation, the pg-boss workers, and `scripts/` (maintainer
|
|
// tooling is not production, but it is a legitimate non-test consumer, so a
|
|
// module reached only from a script is not the thing we are hunting). The `!`
|
|
// suffix is inert in the default pass, so both modes read one config.
|
|
//
|
|
// This is a review tool, not a second gate, for two reasons written down so
|
|
// the next reader does not have to rediscover them:
|
|
//
|
|
// 1. It reports 22 files as of 2026-08-31. Some are test-only by
|
|
// construction (the guard helpers under `src/__tests__/helpers/`, the
|
|
// settings section harness, a score fixture) and some are deliberately
|
|
// unreachable from production (`src/lib/ai/mock-client.ts` is excluded
|
|
// structurally by the `PROVIDER_CHAIN_TYPES` allowlist). Baselining the
|
|
// rest without triaging each one would encode noise as an invariant.
|
|
//
|
|
// Re-measure the count when you touch this block. It said 21 until the
|
|
// v1.38.0 score fixture landed, and a number nobody re-runs drifts
|
|
// quietly until the whole paragraph reads as guesswork.
|
|
//
|
|
// One entry is on that list ON PURPOSE and should stay:
|
|
// `src/lib/signals/adapters/metric-status.ts`. Its only importer is
|
|
// `src/lib/signals/__tests__/registry-invariants.test.ts`, which is
|
|
// exactly what the module is for — it projects the signal registry onto
|
|
// the `MetricStatusMeta` shape so that test can assert the two agree
|
|
// field-for-field and catch future drift. Deleting it to clear the line
|
|
// would remove a check rather than ballast. The production pass is right
|
|
// about the mechanics here and wrong about the conclusion, which is the
|
|
// whole reason this is a review tool and not a gate.
|
|
// 2. It has false positives, though not always the same ones.
|
|
// `src/lib/pwa/sw-cache-policy.ts` is the standing example: it runs in
|
|
// every browser, `public/sw.js` mirrors its logic by hand because a
|
|
// service worker cannot import app modules, and `sw.js:83` names that
|
|
// lockstep. Nothing static can see that edge.
|
|
//
|
|
// This slot used to cite `src/lib/mood/note-backfill.ts`, reported
|
|
// because `scripts/` sits outside the tsconfig that defines the `@/`
|
|
// alias. That one no longer appears — the module and its importing
|
|
// script both still exist, so the resolution improved under us. Left
|
|
// here as a note rather than deleted, because it is the shape of the
|
|
// problem: an example that heals silently makes the surrounding
|
|
// reasoning look wrong when someone checks it.
|
|
//
|
|
// Run it in the deep-audit step, the same way
|
|
// `scripts/audit-column-readers.ts` is run: read the list, judge each entry,
|
|
// do not treat the exit code as a verdict.
|
|
{
|
|
"$schema": "https://unpkg.com/knip@6/schema.json",
|
|
// `!` marks an entry as production. Read the block above before adding or
|
|
// removing one — the suffix is what separates the two passes.
|
|
"entry": [
|
|
"src/app/**/page.tsx!",
|
|
"src/app/**/layout.tsx!",
|
|
"src/app/**/route.ts!",
|
|
"src/app/**/loading.tsx!",
|
|
"src/app/**/not-found.tsx!",
|
|
"src/app/**/error.tsx!",
|
|
"src/app/**/global-error.tsx!",
|
|
"src/app/**/template.tsx!",
|
|
"src/app/**/opengraph-image.tsx!",
|
|
"src/app/**/twitter-image.tsx!",
|
|
"src/app/**/icon.tsx!",
|
|
"src/app/**/apple-icon.tsx!",
|
|
"src/app/**/manifest.ts!",
|
|
"src/app/**/robots.ts!",
|
|
"src/app/**/sitemap.ts!",
|
|
"src/app/**/default.tsx!",
|
|
"src/proxy.ts!",
|
|
"src/instrumentation.ts!",
|
|
"src/lib/jobs/**/*.ts!",
|
|
"src/lib/ai/coach/eval/judge.ts!",
|
|
"scripts/**/*.ts!",
|
|
"scripts/**/*.mjs!",
|
|
"e2e/**/*.spec.ts",
|
|
"e2e/**/*.test.ts",
|
|
"tests/**/*.test.ts",
|
|
"tests/**/setup.ts",
|
|
"vitest.config.ts",
|
|
"vitest.config.integration.ts",
|
|
"playwright.config.ts",
|
|
"next.config.ts!",
|
|
"eslint.config.*",
|
|
"knip.jsonc",
|
|
],
|
|
"project": [
|
|
"src/**/*.{ts,tsx}!",
|
|
"scripts/**/*.{ts,mjs}!",
|
|
"tests/**/*.ts",
|
|
"e2e/**/*.ts",
|
|
],
|
|
"ignore": [
|
|
"src/generated/**",
|
|
"prisma/**",
|
|
"public/**",
|
|
".next/**",
|
|
"**/__mocks__/**",
|
|
"e2e/setup/test-helpers.ts",
|
|
"src/lib/logging/index.ts",
|
|
// v1.42 release-branch contract stubs: each is created ahead of its
|
|
// consumers so the packages built in parallel share one signature. Drop
|
|
// a line the moment its first consumer lands; the release integration
|
|
// checklist removes whatever is left before the tag.
|
|
"src/lib/environment/air-quality-contract.ts",
|
|
// The day view and timeline contract (#613): constants and wire types the
|
|
// server, the two views and the Coach/MCP tool build against.
|
|
"src/lib/day/contract.ts",
|
|
],
|
|
"ignoreDependencies": [
|
|
"@types/node",
|
|
"@types/react",
|
|
"@types/react-dom",
|
|
"@hookform/resolvers",
|
|
"react-hook-form",
|
|
"@prisma/client",
|
|
"next-themes",
|
|
"@vitejs/plugin-react",
|
|
"shadcn",
|
|
"tailwindcss",
|
|
"testcontainers",
|
|
"tw-animate-css",
|
|
"@napi-rs/canvas",
|
|
"postcss",
|
|
],
|
|
"ignoreBinaries": [
|
|
"docker",
|
|
"docker-compose",
|
|
"pg_isready",
|
|
"tsx",
|
|
"cosign",
|
|
// The runtime GeoLite2 fetch extracts in pure Node, but its test builds a
|
|
// MaxMind-shaped tar.gz fixture with the POSIX `tar` (present in CI + dev).
|
|
"tar",
|
|
],
|
|
// Scoped to a single file: an export used only inside its own module is not
|
|
// a finding. It is also why the default pass cannot answer the question the
|
|
// production pass answers — this setting is about exports, not reachability.
|
|
//
|
|
// It had a second effect nobody asked for, worth knowing because it means
|
|
// the gate under-reported for a year. Until knip 6.28.0 this setting also
|
|
// exempted every RE-EXPORT: a barrel line was unconditionally marked
|
|
// "referenced in its own file", so `export { x } from "./x"` that nothing
|
|
// imported was never reported. knip 6.28.0 (PR webpro-nl/knip#1895, fixing
|
|
// issue #1894 — `--fix` deleted the source export and left the barrel line
|
|
// behind, emitting code that did not compile) dropped the exemption. The
|
|
// upgrade from 6.16.1 took this repo from 0 findings to 206 on unchanged
|
|
// code; all but two were barrel lines with no importer, and they are gone
|
|
// now. The suppression was entirely gated on this setting — with it off,
|
|
// 6.16.1 and 6.32.2 agree exactly. So a green Dead-code gate on any knip
|
|
// before 6.28.0 said nothing about re-exports.
|
|
"ignoreExportsUsedInFile": true,
|
|
"ignoreIssues": {
|
|
"src/components/ui/**": ["exports", "types"],
|
|
"src/lib/validations/**": ["types"],
|
|
"src/hooks/_internal/use-query-client-safe.ts": ["exports"],
|
|
"src/lib/google-health/sync.ts": ["exports"],
|
|
},
|
|
}
|