Files
Maurice feef872776 ci(client): lint:pairs keeps a desktop view and its phone twin on one hook
Most features have a desktop view and a phone view, and until now each
carried its own copy of the feature's logic, so a fix on one side drifted
away from the other. With the logic moved into one shared hook per
feature, scripts/feature-pairs.json names every feature with its hooks
and the desktop and phone files that run on them.

lint:pairs fails when a listed view stops importing one of its pair's
hooks (a type only import does not count), when a listed file is gone,
when a hook sits in a view layer rather than under components, hooks,
utils or the folder of a page under pages/, and when a file under
src/mobile/screens is in no pair and not under mobileOnly with the
reason it has no twin. A new phone screen is so either wired to the
desktop feature's hook or marked as phone only on purpose. lint:dup
catches the copies that look alike; this one catches the copies written
anew.

The manifest starts with 120 features and 62 phone only screen files,
each with the reason it stays on the phone alone.

client/CLAUDE.md says how to change a feature, add one with both views
and add a phone screen.
2026-10-09 15:20:10 +02:00

27 lines
1.4 KiB
JavaScript

#!/usr/bin/env node
/*
* lint:pairs: a desktop view and its phone twin run on the same logic.
*
* Most features have a desktop view under components/ or pages/ and a phone
* view under mobile/, and each used to carry its own copy of the feature's
* state, loading and handlers, so a fix on one side drifted away from the
* other. The logic now lives in one shared hook per feature, and
* scripts/feature-pairs.json names, for every feature, the hooks and the
* desktop and phone files that run on them. The check fails when a listed
* view stops importing one of its pair's hooks, when a listed file is gone,
* when a hook sits in a view layer, and when a file under src/mobile/screens
* is in no pair and not under mobileOnly with the reason it has no twin. A
* new phone screen is so either wired to the desktop feature's hook or marked
* as phone only on purpose, never a quiet second copy. lint:dup catches the
* copies that look alike; this catches the ones written anew.
*
* npm run lint:pairs check the manifest against the tree (CI)
* npm run lint:pairs -- --list print every pair with its hooks
*/
import { fileURLToPath } from 'node:url';
import { check } from './lib/pairs.mjs';
import { runCli } from './lib/ratchet.mjs';
const root = fileURLToPath(new URL('..', import.meta.url));
await runCli('lint:pairs', (args) => check({ root, list: args.includes('--list') }));