@noctcore/lint-meta-rules 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/index.cjs +748 -0
- package/dist/index.d.cts +395 -0
- package/dist/index.d.ts +395 -0
- package/dist/index.js +706 -0
- package/docs/rules/agents-doc-presence.md +40 -0
- package/docs/rules/canonical-helpers-single-home.md +35 -0
- package/docs/rules/file-size-ratchet.md +72 -0
- package/docs/rules/layer-rank.md +44 -0
- package/docs/rules/no-cloned-component-folders.md +40 -0
- package/docs/rules/no-warn-severity.md +34 -0
- package/docs/rules/package-shape.md +49 -0
- package/docs/rules/test-runner-segregation.md +40 -0
- package/docs/rules/test-sibling-enforcement.md +35 -0
- package/docs/rules/test-workspace-enrollment.md +41 -0
- package/docs/rules/ui-primitive-shape.md +41 -0
- package/docs/rules/workspace-graph-parity.md +41 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @noctcore/lint-meta-rules
|
|
2
|
+
|
|
3
|
+
Portable, parameterized **lint-meta** rules — whole-repo / cross-file invariants that ESLint's
|
|
4
|
+
per-file AST model cannot reach (every `package.json` name matches a convention, every imported
|
|
5
|
+
workspace package is a declared dependency, file-size ratchets, agent-doc presence, and more).
|
|
6
|
+
|
|
7
|
+
Each rule implements the portable [`IMetaRule`](https://www.npmjs.com/package/@noctcore/harness)
|
|
8
|
+
contract published by `@noctcore/harness`: a pure function of an `IMetaCtx` returning `IViolation[]`.
|
|
9
|
+
|
|
10
|
+
## How this package is consumed
|
|
11
|
+
|
|
12
|
+
This is a **versioned source catalog**, not a runtime dependency you `require()` from a consumer's
|
|
13
|
+
registry. The `@noctcore/harness` `lint-meta` subcommand runs a *bounded eval* that executes only one
|
|
14
|
+
local `.nightcore/lint-meta/registry.js` and never resolves arbitrary imports — a deliberate security
|
|
15
|
+
boundary, since that file runs inside a foreign CI. So the intended integration point is nightcore's
|
|
16
|
+
harness **export pipeline**: it reads a rule's source here, inlines/transforms it, and emits flat
|
|
17
|
+
JavaScript directly into a consumer's `.nightcore/lint-meta/`. No consumer registry imports this
|
|
18
|
+
package at runtime.
|
|
19
|
+
|
|
20
|
+
Publishing to npm is for versioning and discoverability; it is not a "`npm install` this and
|
|
21
|
+
`require()` it" pitch.
|
|
22
|
+
|
|
23
|
+
## Why factories
|
|
24
|
+
|
|
25
|
+
`IMetaRule.run(ctx)` takes no config, so every rule that hardcoded a nightcore-specific anchor (a
|
|
26
|
+
`@nightcore` scope, an `apps/web/src` root, a rank table) is exported as a **factory** —
|
|
27
|
+
`createXRule(options): IMetaRule` — with those anchors lifted to typed options carrying sensible
|
|
28
|
+
defaults. A programmatic caller (or the export pipeline) constructs each rule with the consumer's own
|
|
29
|
+
options:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { createPackageShapeRule, createFileSizeRatchetRule } from '@noctcore/lint-meta-rules';
|
|
33
|
+
|
|
34
|
+
const rules = [
|
|
35
|
+
createPackageShapeRule({ scope: '@acme' }),
|
|
36
|
+
createFileSizeRatchetRule({ id: 'web-file-size-ratchet', roots: ['apps/web/src'], cap: 400 }),
|
|
37
|
+
];
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`RULE_FACTORIES` (an id → factory map), `RULE_IDS`, and `createAllRules()` are exported for iteration
|
|
41
|
+
over the whole catalog.
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
13 nightcore lint-meta rules are ported as 12 factories — nightcore's `web-file-size-ratchet` and
|
|
46
|
+
`engine-file-size-ratchet` were byte-identical logic and collapse into a single
|
|
47
|
+
`createFileSizeRatchetRule` (instantiated once per capped area).
|
|
48
|
+
|
|
49
|
+
| Factory | Source rule(s) | Category | What it enforces |
|
|
50
|
+
| --- | --- | --- | --- |
|
|
51
|
+
| [`createNoWarnSeverityRule`](./docs/rules/no-warn-severity.md) | `no-warn-severity` | config | ESLint severity is `error`/`off`, never `warn`. |
|
|
52
|
+
| [`createPackageShapeRule`](./docs/rules/package-shape.md) | `package-shape` | config | Every workspace is named `<scope>/<dir>`; libraries expose a barrel and point build fields at `dist/`. |
|
|
53
|
+
| [`createWorkspaceGraphParityRule`](./docs/rules/workspace-graph-parity.md) | `workspace-graph-parity` | config | Imported `<scope>/*` specifiers are declared `workspace:*` deps and mirrored in tsconfig references. |
|
|
54
|
+
| [`createLayerRankRule`](./docs/rules/layer-rank.md) | `layer-rank` | source-text | A module imports only strictly-lower-ranked `<scope>` packages (no sideways/upward edges). |
|
|
55
|
+
| [`createFileSizeRatchetRule`](./docs/rules/file-size-ratchet.md) | `web-file-size-ratchet`, `engine-file-size-ratchet` | source-text | Source files stay under a line cap, with a one-way self-tightening baseline ratchet. |
|
|
56
|
+
| [`createAgentsDocPresenceRule`](./docs/rules/agents-doc-presence.md) | `agents-doc-presence` | source-text | An agent-contract doc exists at the root, every surface, and every non-opted-out package. |
|
|
57
|
+
| [`createTestSiblingEnforcementRule`](./docs/rules/test-sibling-enforcement.md) | `test-sibling-enforcement` | source-text | Every source file matched by `include` has a colocated sibling test. |
|
|
58
|
+
| [`createCanonicalHelpersSingleHomeRule`](./docs/rules/canonical-helpers-single-home.md) | `canonical-helpers-single-home` | source-text | A helper symbol is not exported from two different helper homes. |
|
|
59
|
+
| [`createNoClonedComponentFoldersRule`](./docs/rules/no-cloned-component-folders.md) | `no-cloned-component-folders` | source-text | A component folder name exists under only one feature (shrinking allowlist). |
|
|
60
|
+
| [`createUiPrimitiveShapeRule`](./docs/rules/ui-primitive-shape.md) | `ui-primitive-shape` | source-text | A folder primitive ships its proof siblings; a flat primitive carries none at the ui root. |
|
|
61
|
+
| [`createTestWorkspaceEnrollmentRule`](./docs/rules/test-workspace-enrollment.md) | `test-workspace-enrollment` | testing | Every tested package is enumerated in the aggregate test script. |
|
|
62
|
+
| [`createTestRunnerSegregationRule`](./docs/rules/test-runner-segregation.md) | `test-runner-segregation` | testing | Bun-side and foreign-side test runners are never mixed within a package. |
|
|
63
|
+
|
|
64
|
+
Every factory is callable with no arguments (all options default), so `createAllRules()` and
|
|
65
|
+
per-factory defaults work out of the box; supply options to retarget a rule at your own repo.
|