@geonosis/oxlint-plugin-biological-architecture 2.6.1 → 2.8.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/CHANGELOG.md +59 -0
- package/README.md +0 -2
- package/RULES.md +12 -39
- package/corpus/.oxlintrc.json +0 -18
- package/corpus/manifest.json +0 -2
- package/dist/{chunk-KV7JRNAP.js → chunk-24K5232K.js} +0 -2
- package/dist/index.d.ts +11 -1
- package/dist/index.js +221 -262
- package/dist/presets.js +1 -1
- package/package.json +2 -2
- package/corpus/domains/document/workflows/bad-per-kind-saga.ts +0 -3
- package/corpus/domains/document/workflows/bad-per-kind-workflow.ts +0 -5
- package/corpus/domains/document/workflows/good-minted-workflow.ts +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @geonosis/oxlint-plugin-biological-architecture
|
|
2
2
|
|
|
3
|
+
## 2.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e880a6c: The tiers have no dead ends a consumer can reach (#1, #2). Three shapes from one migration had no
|
|
8
|
+
legal expression, because two rules together forbade every place the file could live:
|
|
9
|
+
|
|
10
|
+
- **`tissue-no-data-props`** accepts layout configuration: a `number` or `boolean` prop the tissue
|
|
11
|
+
gives a literal default (`initialCount = 10`, `wrap = false`). A stateless adapter between two
|
|
12
|
+
cells is a tissue, and now it can be one. A string, a default that is not a literal of the prop's
|
|
13
|
+
type, and a primitive with no default are still data.
|
|
14
|
+
- **`no-hook-in-component-disguise`** accepts the client-boundary beacon: a file whose directive
|
|
15
|
+
prologue says `'use client'`, whose component calls a hook and returns only `null`. Its parent — a
|
|
16
|
+
Server Component, or a tissue under `tissue-no-hooks` — cannot call the hook, so there was no
|
|
17
|
+
real component to move it into. A `'use client'` component that returns its `children`, or calls
|
|
18
|
+
no hook, is still reported. The no-hook message now tells a layout about metadata
|
|
19
|
+
(`passthroughLayout`) and tells any other component nothing of the kind.
|
|
20
|
+
- **`no-invalid-feature-folders`** takes `roots` (default: none). Directly under each declared
|
|
21
|
+
directory, a folder that is not a tier is a finding per file, so an unmigrated pile
|
|
22
|
+
(`src/components/organisms/`) is debt the ratchet counts and moving a file into it grows the
|
|
23
|
+
count, instead of silently clearing every tier rule.
|
|
24
|
+
|
|
25
|
+
`cell-must-not-compose-cell` keeps no exception; its fix now names the stateful host: two cells
|
|
26
|
+
side by side, coordinating through the store, arranged by a tissue.
|
|
27
|
+
|
|
28
|
+
## 2.7.0
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- 08c9653: The kit knows no document kind. `document-sagas-are-generic` and `documents-share-one-table` are
|
|
33
|
+
gone from the plugin and from the `backend-workflows` preset, with their corpus and fixtures: both
|
|
34
|
+
took a list of one consumer's document kinds (`perKindPrefixes`, `perKindTables`) and enforced a
|
|
35
|
+
vocabulary the kit has no business holding — a document entity is whatever extends `Document`, and
|
|
36
|
+
the registry a consumer builds is the only enumeration there is. Their intent is held by types
|
|
37
|
+
now: a consumer's per-entity maps are folds over the registry, and a per-entity saga has nowhere to
|
|
38
|
+
be written once `documentWorkflows` mints them. Their ids stay for one release: oxlint refuses a
|
|
39
|
+
config that names a rule its plugin does not export, so a config naming either still parses, the
|
|
40
|
+
id reports nothing and says once that it is retired, and `geonosis doctor` WARNs naming it where
|
|
41
|
+
it would have failed. Migration: remove the block before the next major, when the ids go; the
|
|
42
|
+
doctor's floor table no longer lists them.
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- c8c5d51: `documentWorkflows(entity, { effects, ports })` at `@geonosis/document/workflows` — T3, the org
|
|
47
|
+
workflows over the engine, one body per Document: `create`, `save`, `setStatus`, `remove`, `send`
|
|
48
|
+
(durable), `convert`, `duplicate`, `share`, each named for the entity. A host decides
|
|
49
|
+
`effects.announce(fact)` — the product's events off a `DocumentFact` — and answers three ports,
|
|
50
|
+
`door`, `link` and `mail` (`Result<void, MailUndelivered>` from `better-result`); `beforeCreate`,
|
|
51
|
+
`conversion`, the mail words, `counter`, `actor`, `guard`, `now` and `seed` default, and a
|
|
52
|
+
counter-numbered entity or a template on a host that declares neither is refused by name. The
|
|
53
|
+
factory makes the two steps that reach the outside world, so the durable-body law holds on every
|
|
54
|
+
host. A third entry, like `./store`, so the core stays off every floor and browser-safe. The
|
|
55
|
+
Standard Schema builders the surface wrote for itself move to the core (`objectOf`, `enumOf`,
|
|
56
|
+
`optional`, `nullable`, `arrayOf`, `merge`, the scalars, `validate`) and `SchemaAdapter` is the
|
|
57
|
+
adapter's name (`SurfaceSchemaAdapter` stays as an alias). `@geonosis/workflows` and
|
|
58
|
+
`better-result` join the package's dependencies. The plugin's `document-sagas-are-generic` and
|
|
59
|
+
`documents-share-one-table` no longer carry `floor: pending`: the store shipped at 0.4 and the
|
|
60
|
+
workflows ship here. `documentIdentifiers` spells every identifier as a literal type off the name it was given (`CamelOf`, `DocumentIdentifiers`), so a consumer indexes a typed router map by the camel name without a cast. `documentEntities(map).keyed(pick)` answers one value per entity under its name, total by construction.
|
|
61
|
+
|
|
3
62
|
## 2.6.1
|
|
4
63
|
|
|
5
64
|
## 2.6.0
|
package/README.md
CHANGED
|
@@ -136,8 +136,6 @@ months. Carry these across, or turn the rule off:
|
|
|
136
136
|
| `no-brand-names` | `{ brands, allowedSubstrings }` | refuses the run |
|
|
137
137
|
| `organelle-dependency` | `{ sharedFeatures }` | only `shared` crosses a feature boundary |
|
|
138
138
|
| `cell-no-cross-feature-organelles` | `{ sharedFeatures }` | only `shared` crosses a feature boundary |
|
|
139
|
-
| `documents-share-one-table` | `{ perKindTables }` | refuses the run |
|
|
140
|
-
| `document-sagas-are-generic` | `{ perKindPrefixes }` | refuses the run |
|
|
141
139
|
| `step-opens-its-own-cell` | `{ engine, within, wrapper }` | refuses the run |
|
|
142
140
|
| `no-raw-html-atoms` | the positional element→atom map | refuses the run |
|
|
143
141
|
| `layer-walls` | `{ layers: [{ name, paths, mayImport }], externals? }` | refuses the run |
|
package/RULES.md
CHANGED
|
@@ -9,11 +9,14 @@ Read from the two source trees on 2026-08-29:
|
|
|
9
9
|
One plugin name, two rule sets, no shared code. **33 rules had the same filename in both trees; only
|
|
10
10
|
3 of those 33 were byte-identical.** A fix in one never reached the other.
|
|
11
11
|
|
|
12
|
-
The union here is **
|
|
13
|
-
`
|
|
14
|
-
|
|
15
|
-
`no-
|
|
16
|
-
`
|
|
12
|
+
The union here is **52 rules** — 54 when it was cut, less `document-sagas-are-generic` and
|
|
13
|
+
`documents-share-one-table`, retired in 2.7.0 because both enforced one consumer's document kinds —
|
|
14
|
+
plus twenty-eight the kit wrote for itself: `layer-walls`, `emit-declares-attempts`,
|
|
15
|
+
`cell-no-cross-feature-organelles`, the `backend-medusa` ten, `no-unregistered-plugin-dir` +
|
|
16
|
+
`router-schema-parity`, the `themekit` two, `no-mock-db-in-integration`, `todo-names-its-plan`,
|
|
17
|
+
`boundary-time-is-primitive`, `durable-body-reads-through-steps`, `subpath-over-barrel` and the six
|
|
18
|
+
of the W67 batch — **80**. The two retired ids still resolve for one release, as no-ops that say
|
|
19
|
+
they are retired, so a config naming them parses; they go at the next major.
|
|
17
20
|
Every one of the twenty-eight is marked **written here** in the inventory, and the table below is
|
|
18
21
|
held against that column rather than kept by hand.
|
|
19
22
|
|
|
@@ -22,10 +25,10 @@ held against that column rather than kept by hand.
|
|
|
22
25
|
| in both trees, byte-identical | 3 |
|
|
23
26
|
| in both trees, **diverged** | 30 |
|
|
24
27
|
| dielime only | 3 |
|
|
25
|
-
| during.day only |
|
|
26
|
-
| **union** | **
|
|
28
|
+
| during.day only | 16 |
|
|
29
|
+
| **union** | **52** |
|
|
27
30
|
| written here | 28 |
|
|
28
|
-
| **total** | **
|
|
31
|
+
| **total** | **80** |
|
|
29
32
|
|
|
30
33
|
## How divergence was resolved
|
|
31
34
|
|
|
@@ -513,26 +516,6 @@ Closing it also fixed a hole in the barrel rule's own pattern, which required a
|
|
|
513
516
|
therefore no-op'd on the cwd-relative `cells/index.ts` oxlint reports for a package whose own root
|
|
514
517
|
holds `cells/`.
|
|
515
518
|
|
|
516
|
-
### `documents-share-one-table` — matches `pgTable` as well as `sqliteTable`
|
|
517
|
-
|
|
518
|
-
during.day's fork matched `literalNamedBy(node, 'sqliteTable')` and nothing else, and every tenant
|
|
519
|
-
table on that tree has been `pgTable` since its plan 037. Its own probe: a well-formed per-kind
|
|
520
|
-
table
|
|
521
|
-
|
|
522
|
-
```ts
|
|
523
|
-
export const invoices = pgTable('invoices', { id: text('id').primaryKey(), orgId: orgIdColumn() })
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
under `packages/db/src/schema/tenant/` produced **zero** findings from this rule; only the malformed
|
|
527
|
-
variant was caught, by `tenant-tables-carry-org-id`, and by accident. The fork's rule had been dead
|
|
528
|
-
since the tenant plane moved to Postgres.
|
|
529
|
-
|
|
530
|
-
The kit matching both constructors is therefore a fix, not a widening for its own sake. It stands
|
|
531
|
-
because the rule is about the second storage a base entity retired — which is true whatever the
|
|
532
|
-
dialect — and because `dialect-through-the-seam` already says the dialect is a seam fact rather than
|
|
533
|
-
a thing a document kind gets to have an opinion about. Both branches are exercised through the real
|
|
534
|
-
binary in `src/rules/__fixtures__/packages/db/src/schema/tenant/`, so neither can go quiet again.
|
|
535
|
-
|
|
536
519
|
### `no-raw-html-atoms` — the tier it was always documented for (0.3.0)
|
|
537
520
|
|
|
538
521
|
Its own description said levels 2-6 and it fired at every level, `atoms/` included, where a raw
|
|
@@ -567,13 +550,9 @@ rule the option refusal exists to stop, one option along.
|
|
|
567
550
|
| `organelle-dependency` | `sharedFeatures` | `['shared']` — during.day's `charts`/`document` are config, not law |
|
|
568
551
|
| `mutating-step-declares-retry` | `retryKey` | `maxRetries` — Medusa's key. `@geonosis/workflows` spells the same budget `retry: { limit, backoff }` (`create-step.ts`), and with the key compiled in a correctly budgeted step on that engine was a finding for ever |
|
|
569
552
|
| `mutating-step-declares-retry` | `retryLimitKey` | `limit` — the key that holds the NUMBER when the budget is an object. #191: reading only the bare form let `retry: { limit: 0 }` pass, which is the same silence as `maxRetries: 0` |
|
|
570
|
-
| `documents-share-one-table` | `perKindTables` | **refuses the run** |
|
|
571
553
|
| `worker-handles-are-scoped` | `within` + `wrapper` | **refuses the run** — `withCells` and `/apps/api/src/` were compiled in, so the rule served one repo's layout and one repo's vocabulary and a scope opener called anything else read as unscoped for ever |
|
|
572
554
|
| `subpath-over-barrel` | `packages` (`{ name, subpaths: { <subpath>: string[] } }[]`) | **refuses the run** — which of a repo's own packages expose subpaths, and which names live under each, is a map only that package's owner has |
|
|
573
555
|
| `durable-body-reads-through-steps` | `ports` | **refuses the run** — what a body reaches the outside world through is the repo's vocabulary; `durableKey` / `durableValue` (default `durable: true`) say how a workflow declares itself durable |
|
|
574
|
-
| `document-sagas-are-generic` | `perKindPrefixes` | **refuses the run** |
|
|
575
|
-
| `document-sagas-are-generic` | `within` | **refuses the run** — `/packages/workflows/src/` was compiled in, so the same per-kind saga one directory over was silent and no other layout could enable the rule at all |
|
|
576
|
-
| `document-sagas-are-generic` | `factories` | `['saga', 'createWorkflow']` — the callee was `saga` alone, so a per-entity `createWorkflow('invoice.create', …)` produced no finding (026-W2, measured). A name assembled from the entity is a template literal the rule cannot read: that is the mint the rule sends people to, not a gap in it |
|
|
577
556
|
| `unique-query-step-name` | `queryStepCalls` | **refuses the run** — the two names it shipped with are Medusa framework calls with no counterpart, so on the org engine the rule had zero reach while reading as enforced (026-W2, measured through the binary). There is no second spelling to inherit: `@geonosis/workflows` has no query-step primitive, and a repeated step name there is DEFINED rather than lost — `reserve`, `reserve#2` in call order (`engine.ts:124`) |
|
|
578
557
|
| `no-raw-html-atoms` | (positional) element→atom map | **refuses the run** |
|
|
579
558
|
| `no-raw-html-atoms` | `scope` (second positional, `{ scope: ["cells", …] }`) | every file except the atom tier |
|
|
@@ -710,8 +689,6 @@ has, and one a kit that guessed at it would keep stale on somebody else's behalf
|
|
|
710
689
|
| `compound-no-stores` | frontend | — | `directionRule` | yes | yes | diverged |
|
|
711
690
|
| `constants-in-constants-file` | backend-workflows | — | `paths` | — | yes | during only |
|
|
712
691
|
| `dialect-through-the-seam` | backend-workflows | — | `onImportSource` + `mergeVisitors` + `paths` | — | yes | during only |
|
|
713
|
-
| `document-sagas-are-generic` | backend-workflows | `perKindPrefixes` | `paths` + `options` + `literal-call` | — | yes | during only |
|
|
714
|
-
| `documents-share-one-table` | backend-workflows | `perKindTables` | `paths` + `options` + `literal-call` | — | yes | during only |
|
|
715
692
|
| `durable-body-reads-through-steps` | backend-workflows | `ports` | `nodes` + `objects` + `steps` + `options` | — | — | **written here** (#167, design-026 §8) |
|
|
716
693
|
| `effect-hook-naming` | frontend | — | `paths` | yes | yes | diverged |
|
|
717
694
|
| `emit-declares-attempts` | backend-medusa | — | `options` | — | — | **written here** |
|
|
@@ -867,8 +844,6 @@ option not named here is one no rule reads.
|
|
|
867
844
|
| `compound-no-stores` | — |
|
|
868
845
|
| `constants-in-constants-file` | — |
|
|
869
846
|
| `dialect-through-the-seam` | — |
|
|
870
|
-
| `document-sagas-are-generic` | `factories`, `perKindPrefixes`, `within` |
|
|
871
|
-
| `documents-share-one-table` | `perKindTables` |
|
|
872
847
|
| `durable-body-reads-through-steps` | `durableKey`, `durableValue`, `ports`, `stepFactories`, `stepProxies`, `workflowFactories` |
|
|
873
848
|
| `effect-hook-naming` | — |
|
|
874
849
|
| `emit-declares-attempts` | `budgetHelpers`, `emitters` |
|
|
@@ -892,7 +867,7 @@ option not named here is one no rule reads.
|
|
|
892
867
|
| `no-index-count-as-exact` | `estimateFields`, `labelKey` |
|
|
893
868
|
| `no-inert-hidden-jsx` | — |
|
|
894
869
|
| `no-inline-data-in-jsx` | — |
|
|
895
|
-
| `no-invalid-feature-folders` |
|
|
870
|
+
| `no-invalid-feature-folders` | `roots` |
|
|
896
871
|
| `no-loader-side-effect-in-index-file` | `directories`, `resourceFactories` |
|
|
897
872
|
| `no-logic-in-component-files` | — |
|
|
898
873
|
| `no-mock-db-in-integration` | `dbModules`, `integrationDirs`, `mockNames` |
|
|
@@ -951,8 +926,6 @@ itself, and the doctor says so on the `exercised` line.
|
|
|
951
926
|
|
|
952
927
|
| Rule | Floor | Shipped |
|
|
953
928
|
|---|---|---|
|
|
954
|
-
| `document-sagas-are-generic` | `document` | PENDING |
|
|
955
|
-
| `documents-share-one-table` | `document` | PENDING |
|
|
956
929
|
| `step-opens-its-own-cell` | `workflows` | yes |
|
|
957
930
|
|
|
958
931
|
<!-- END GENERATED FLOORS -->
|
package/corpus/.oxlintrc.json
CHANGED
|
@@ -37,24 +37,6 @@
|
|
|
37
37
|
"biological-architecture/compound-no-stores": "error",
|
|
38
38
|
"biological-architecture/constants-in-constants-file": "error",
|
|
39
39
|
"biological-architecture/dialect-through-the-seam": "error",
|
|
40
|
-
"biological-architecture/document-sagas-are-generic": [
|
|
41
|
-
"error",
|
|
42
|
-
{
|
|
43
|
-
"perKindPrefixes": [
|
|
44
|
-
"invoice"
|
|
45
|
-
],
|
|
46
|
-
"within": "(?:__fixtures__|corpus)/domains/[^/]+/workflows/"
|
|
47
|
-
}
|
|
48
|
-
],
|
|
49
|
-
"biological-architecture/documents-share-one-table": [
|
|
50
|
-
"error",
|
|
51
|
-
{
|
|
52
|
-
"perKindTables": [
|
|
53
|
-
"invoices",
|
|
54
|
-
"quotes"
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
40
|
"biological-architecture/durable-body-reads-through-steps": [
|
|
59
41
|
"error",
|
|
60
42
|
{
|
package/corpus/manifest.json
CHANGED
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
"biological-architecture/compound-no-stores",
|
|
13
13
|
"biological-architecture/constants-in-constants-file",
|
|
14
14
|
"biological-architecture/dialect-through-the-seam",
|
|
15
|
-
"biological-architecture/document-sagas-are-generic",
|
|
16
|
-
"biological-architecture/documents-share-one-table",
|
|
17
15
|
"biological-architecture/durable-body-reads-through-steps",
|
|
18
16
|
"biological-architecture/effect-hook-naming",
|
|
19
17
|
"biological-architecture/emit-declares-attempts",
|
|
@@ -42,8 +42,6 @@ var BACKEND_WORKFLOWS = [
|
|
|
42
42
|
"boundary-time-is-primitive",
|
|
43
43
|
"constants-in-constants-file",
|
|
44
44
|
"dialect-through-the-seam",
|
|
45
|
-
"document-sagas-are-generic",
|
|
46
|
-
"documents-share-one-table",
|
|
47
45
|
"durable-body-reads-through-steps",
|
|
48
46
|
"mutating-step-declares-retry",
|
|
49
47
|
"no-date-string-compare",
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,16 @@ type ProbeTree = {
|
|
|
36
36
|
};
|
|
37
37
|
type ProbeFn = (options: readonly unknown[]) => Probe | ProbeTree;
|
|
38
38
|
|
|
39
|
+
type RetiredRule = Rule & {
|
|
40
|
+
meta: Rule['meta'] & {
|
|
41
|
+
retired: {
|
|
42
|
+
reason: string;
|
|
43
|
+
since: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
declare const RETIRED_RULES: Record<'document-sagas-are-generic' | 'documents-share-one-table', RetiredRule>;
|
|
48
|
+
|
|
39
49
|
type Rule = {
|
|
40
50
|
create: (context: never) => Record<string, unknown>;
|
|
41
51
|
fixShape: string;
|
|
@@ -123,4 +133,4 @@ declare const plugin: {
|
|
|
123
133
|
rules: Record<string, Rule>;
|
|
124
134
|
};
|
|
125
135
|
|
|
126
|
-
export { Preset, type Rule, type RuleName, plugin as default, rules };
|
|
136
|
+
export { Preset, RETIRED_RULES, type Rule, type RuleName, plugin as default, rules };
|