Repository navigation
v1.4.0
Minor Changes
-
#22
67be5ddThanks @stevensacks! - Enable architecture-boundary enforcement. Turn on
import-x/no-restricted-pathsaterrorin theguardrailslayer, scoped to
the app non-test/story file set (${sourceDir}/**/!(*.test|*.stories).ts?(x)).
No new dependency:eslint-plugin-import-x(v4.16.2) is already wired in, and
airbnb-extended ships this ruleoff, whichguardrails(spread afterbase)
now overrides.It encodes GAIA's canonical
app/layout and its import-direction invariant.
Imports may only flow from a higher layer to a lower one;types/is a pure
leaf importable by everyone:routes -> pages -> components -> { hooks, state } -> services -> utils -> typesOne zone per lower layer names the higher layers it must not import (collapsed
withfromarrays, supported in 4.16.2). Becauseroutesis in everyfrom
set, nothing may import a route.middleware,sessions.server,assets,
languages, andstylesare intentionally left unconstrained.Zone
target/frompaths resolve againstprocess.cwd()(the consuming
project's root where eslint runs), not this package's location in
node_modules, so./${sourceDir}/...correctly points at the consumer's source
tree. NobasePathoverride is needed. Verified by running eslint against the
GAIA React reference app: the zones fire onapp/**files and resolve the~
alias against the consumer root.Downstream impact (loud, but a minor by request): this is
error-level and
catchesimport typeas well as value imports, so a consumer whose code
currently crosses a layer boundary will see a NEW lint failure on upgrade. It
is not auto-fixable; each hit is a real wrong-direction edge to relocate or an
inlineeslint-disableto add deliberately. The reference app surfaced exactly
one edge across all ofapp/: a component importing a resource-routeaction
type foruseFetcher<typeof action>(). Treat such hits as signal, not noise.
If a consumer relies on resource routes as a typed data-endpoint layer, relax
only thecomponents->routesreach with the rule'sexceptoption rather
than downgrading the rule. -
#20
056d935Thanks @stevensacks! - Harden thetestingconfig with test-discipline rules beyond the
@vitest/eslint-pluginrecommendedpreset (all verified against plugin
v1.6.19). These complement a mechanical TDD RED-verification gate by closing
test-integrity gaps the gate cannot see on its own.Added (error):
consistent-test-it{fn: 'test'}— forbid mixingtest()/it(); GAIA
usestest()exclusively.fncascades to within-describe in 1.6.19.consistent-vitest-vi{fn: 'vi'}— forbid mixing thevitest/vimock
API; GAIA usesvi.no-test-return-statement— a returned value/promise can resolve after the
test "passes", faking GREEN.no-conditional-in-test— a branch in a test body can assert nothing on one
path. (Only this one;no-conditional-testsis a byte-identical duplicate.)no-test-prefixes— forbidfdescribe/fit/xdescribe/xit, which bypass
the activeno-focused-tests/no-disabled-testsrules.prefer-todo— push emptytest('...')stubs totest.todo('...')so
unimplemented tests are explicit, not silently passing. (Notwarn-todo,
which contradicts it.)require-to-throw-message— a bare.toThrow()passes on any throw; require
an asserted message or matcher.
Changed (baseline bump):
no-disabled-testswarn->error—.skipis the biggest gaming vector
for a RED-verification gate. Park work withtest.todoor an inline
eslint-disable, not a silent.skip.
Downstream impact: these are
error-level, so projects with existing
violations may see new lint failures. Most additions are auto-fixable
(eslint --fix);no-disabled-testsandrequire-to-throw-messageare not.
Verified zero spurious fires across GAIA's 44 test/story files.