@starci/hfs 4.7.46 → 4.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 +16 -0
- package/README.md +4 -9
- package/package.json +11 -5
- package/runtime/knowledge/grammars/{starci → core}/playbook.yaml +3 -3
- package/runtime/knowledge/grammars/index.yaml +14 -23
- package/runtime/knowledge/grammars/offset-pop/playbook.yaml +2 -2
- package/runtime/knowledge/hfs/canon-pins.yaml +19 -20
- package/runtime/knowledge/hfs/fe-stack.yaml +1 -1
- package/runtime/knowledge/hfs/rules.yaml +60 -60
- package/runtime/modules/kernel/failure-codes.yaml +13 -13
- package/runtime/scripts/hfs/rule-catalog.mjs +2 -2
- package/runtime/scripts/lib/example-refs.mjs +10 -3
- package/runtime/scripts/lib/grammar-lint.mjs +16 -3
- package/scaffold/app.mjs +2 -2
- package/stack/render.mjs +3 -1
- package/sync/hygiene.mjs +1 -1
- package/sync/index.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.8.0 - 2026-10-27
|
|
4
|
+
|
|
5
|
+
- Removed: the Heritage family from the bundled Grammar catalog.
|
|
6
|
+
- Changed: the bundled canon pins name each @starci package by its folder in starci-harness (`source: packages/<name>/package.json`) at the versions there; `@starci/cli` is a registry-only pin.
|
|
7
|
+
- Removed: the specs that exercised the legacy runtime's own scripts (css-rules, grammar-knowledge, grammar-union-census, grammar-vendor-repaints, ui-proof-*); that code is not part of this package.
|
|
8
|
+
- Changed: the package lives in github.com/starci183/starci-harness under `packages/` and publishes from there; its bundled `runtime/` is committed source, edited in place (no generator, no `prepack`/`pretest` hook).
|
|
9
|
+
- Changed: owner ruling: the Grammar catalog has exactly two families, `core` and `offset-pop`. `grammarLintFor`,
|
|
10
|
+
`grammarFamilyFor`, `grammarContractFor`, `resolveGrammarFamily` and the code-pattern family binding
|
|
11
|
+
(`familyCanons.core`) answer by those ids; `starci app` scaffolds `sides.fe.grammar: core`; the core lint package is
|
|
12
|
+
`@starci/eslint-grammar-core` with `coreGrammarConfig`, and the knowledge folder is `knowledge/grammars/core`.
|
|
13
|
+
- Removed: `starci` and `starci-core` are not family ids and have no alias; a selection naming them is refused.
|
|
14
|
+
|
|
15
|
+
## 4.7.47 - 2026-10-27
|
|
16
|
+
|
|
17
|
+
- Fixed: the rendered stack escapes every literal dollar once more, so a secret-reading command or healthcheck survives the second interpolation of docker stack deploy.
|
|
18
|
+
|
|
3
19
|
## 4.7.46 - 2026-10-26
|
|
4
20
|
|
|
5
21
|
- Changed: owner ruling push-main-after-scoped-check reaches product apps: the generated pre-push hook passes a fast-forward main push when the hooks pass and the secret scan is clean, a v* tag must be annotated, and app CI runs on pushes to main.
|
package/README.md
CHANGED
|
@@ -192,15 +192,10 @@ The upload authenticates with GitHub's OIDC token: the managed `ci.yml` job has
|
|
|
192
192
|
|
|
193
193
|
## Maintaining the bundle
|
|
194
194
|
|
|
195
|
-
`runtime/`
|
|
196
|
-
`scripts/hfs/architecture.mjs
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
`knowledge/hfs/canon-pins.yaml`, `knowledge/patterns/fe/folder.yaml` or the catalog entries of those codes, run `starci release sync-runtime`;
|
|
200
|
-
`starci release sync-runtime --check` fails on a stale copy. Bump `version` here and in the pin when the behaviour changes.
|
|
201
|
-
|
|
202
|
-
The examples workflow (`.github/workflows/examples.yml`) runs `starci app lint` of this CLI at the root of every `examples/*`
|
|
203
|
-
app with an `hfs.json` (each `examples/<app>` root) and fails on any finding or any tool that could not run. This includes the ESLint canons and repository checks also run by `starci app check`, plus stylelint over the frontend stylesheets.
|
|
195
|
+
`runtime/` holds the slot loader files, the pins, the import closure of `scripts/hfs/check.mjs` and
|
|
196
|
+
`scripts/hfs/architecture.mjs`, and the catalog slice of every code `starci app check` can emit. It is committed source of
|
|
197
|
+
this package, edited in place ([packages/README.md](../README.md) says how the bundled copies move together). Bump
|
|
198
|
+
`version` here and in the pin when the behaviour changes.
|
|
204
199
|
|
|
205
200
|
## Serving knowledge to other packages
|
|
206
201
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/hfs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "The StarCi app command implementation for scaffolding, linting, checking and synchronizing one product repository.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"author": "starci183",
|
|
8
|
+
"homepage": "https://github.com/starci183/starci-harness/tree/main/packages/hfs#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/starci183/starci-harness.git",
|
|
12
|
+
"directory": "packages/hfs"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/starci183/starci-harness/issues"
|
|
16
|
+
},
|
|
7
17
|
"private": false,
|
|
8
18
|
"exports": {
|
|
9
19
|
".": "./src/main.mjs",
|
|
@@ -60,10 +70,6 @@
|
|
|
60
70
|
"access": "public"
|
|
61
71
|
},
|
|
62
72
|
"scripts": {
|
|
63
|
-
"sync": "node ../../scripts/hfs/sync-runtime.mjs",
|
|
64
|
-
"sync:check": "node ../../scripts/hfs/sync-runtime.mjs --check",
|
|
65
|
-
"prepack": "node prep-runtime.mjs",
|
|
66
|
-
"pretest": "node prep-runtime.mjs",
|
|
67
73
|
"test": "node --test \"src/*.spec.mjs\""
|
|
68
74
|
}
|
|
69
75
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
schema: starci/knowledge-source@1
|
|
2
|
-
id: grammar.
|
|
2
|
+
id: grammar.core.playbook
|
|
3
3
|
title: StarCi Core — playbook
|
|
4
4
|
purpose: |
|
|
5
5
|
Which idioms a business shape asks for, and what a supplied reference is allowed to contribute to
|
|
@@ -12,7 +12,7 @@ purpose: |
|
|
|
12
12
|
has yet shown them twice; `guidance` holds the rules every Core app built on them follows.
|
|
13
13
|
appliesTo:
|
|
14
14
|
- grammar
|
|
15
|
-
family:
|
|
15
|
+
family: core
|
|
16
16
|
provenance:
|
|
17
17
|
publicEntry: "@starci/grammar/common"
|
|
18
18
|
package: "@starci/grammar"
|
|
@@ -269,7 +269,7 @@ shapes:
|
|
|
269
269
|
by presentation.groupIdentity.
|
|
270
270
|
notes: |
|
|
271
271
|
FE-RULE-OWNERSHIP in knowledge/patterns/fe/index.yaml separates universal app-shell semantics
|
|
272
|
-
from these family APIs, values, shapes and effects. @starci/eslint-grammar-
|
|
272
|
+
from these family APIs, values, shapes and effects. @starci/eslint-grammar-core owns their
|
|
273
273
|
code checks. Inspect installed Grammar exports and the running shell when proving the recipe.
|
|
274
274
|
|
|
275
275
|
readingSteps:
|
|
@@ -24,7 +24,7 @@ guidance:
|
|
|
24
24
|
Do not treat this catalog as selecting a default Grammar family. Family choice belongs to the
|
|
25
25
|
current design specification and its explicit sides.fe.grammar declaration.
|
|
26
26
|
rationale: |
|
|
27
|
-
Silent fallback to
|
|
27
|
+
Silent fallback to a family would invent product direction and override an absent/ambiguous design.
|
|
28
28
|
- id: verify-before-use
|
|
29
29
|
requirement: |
|
|
30
30
|
Before applying snapshot APIs or recorded gaps, inspect the selected repository's package
|
|
@@ -47,11 +47,11 @@ topics:
|
|
|
47
47
|
Generated DNA snapshot of the `@starci/grammar/common` public entry: custom properties,
|
|
48
48
|
the 110 renderers of its registry, their classes, stamped rule ids and recorded gaps. The DNA owns the observed package
|
|
49
49
|
version and source inventory. Common supplies anatomy, not colour. The snapshot is drift-checked.
|
|
50
|
-
- id:
|
|
51
|
-
path:
|
|
52
|
-
title:
|
|
50
|
+
- id: core
|
|
51
|
+
path: core/index.yaml
|
|
52
|
+
title: Core Grammar
|
|
53
53
|
summary: |
|
|
54
|
-
Historical snapshot of the
|
|
54
|
+
Historical snapshot of the core family — DNA, idioms, playbook (including composing the
|
|
55
55
|
0.5.0 forms, overlays and navigation chrome) and family boundaries.
|
|
56
56
|
- id: offset-pop
|
|
57
57
|
path: offset-pop/index.yaml
|
|
@@ -61,16 +61,7 @@ topics:
|
|
|
61
61
|
shadow, one pink decision accent with a text-safe accent for text — with DNA, idioms, a
|
|
62
62
|
mobile-first playbook for playful learning or consumer apps, and family boundaries including two
|
|
63
63
|
decisions flagged for the family owner.
|
|
64
|
-
- id: heritage
|
|
65
|
-
path: heritage/DNA.yaml
|
|
66
|
-
title: Heritage Grammar
|
|
67
|
-
summary: |
|
|
68
|
-
Generated snapshot of the Heritage family's parity declaration, arrangement, scoped tokens and Common renderers.
|
|
69
64
|
families:
|
|
70
|
-
- id: heritage
|
|
71
|
-
title: heritage
|
|
72
|
-
contractRef: common
|
|
73
|
-
packageSnapshot: heritage/DNA.yaml
|
|
74
65
|
- id: common
|
|
75
66
|
title: common
|
|
76
67
|
componentContract:
|
|
@@ -85,18 +76,18 @@ families:
|
|
|
85
76
|
(`defineGrammarFamily`), not a family that ships a palette, so `authority`, `reusableStyle`,
|
|
86
77
|
`productComposition` and `index` have nothing to name here. Universal semantics, renderer anatomy,
|
|
87
78
|
state and accessibility remain owned by knowledge/ui.
|
|
88
|
-
- id:
|
|
89
|
-
title:
|
|
79
|
+
- id: core
|
|
80
|
+
title: core
|
|
90
81
|
contractRef: common
|
|
91
82
|
lint:
|
|
92
|
-
package: '@starci/eslint-grammar-
|
|
93
|
-
factory:
|
|
83
|
+
package: '@starci/eslint-grammar-core'
|
|
84
|
+
factory: coreGrammarConfig
|
|
94
85
|
prefix: starci-grammar
|
|
95
|
-
authority:
|
|
96
|
-
packageSnapshot:
|
|
97
|
-
reusableStyle:
|
|
98
|
-
productComposition:
|
|
99
|
-
index:
|
|
86
|
+
authority: core/family.yaml
|
|
87
|
+
packageSnapshot: core/DNA.yaml
|
|
88
|
+
reusableStyle: core/idioms.yaml
|
|
89
|
+
productComposition: core/playbook.yaml
|
|
90
|
+
index: core/index.yaml
|
|
100
91
|
- id: offset-pop
|
|
101
92
|
title: offset-pop
|
|
102
93
|
contractRef: common
|
|
@@ -289,14 +289,14 @@ guidance:
|
|
|
289
289
|
presentation:
|
|
290
290
|
font:
|
|
291
291
|
ownership: FE-RULE-OWNERSHIP
|
|
292
|
-
inherits:
|
|
292
|
+
inherits: core
|
|
293
293
|
contract: |
|
|
294
294
|
Offset Pop keeps Common typography renderers and props. Its font proof reads the shared Common
|
|
295
295
|
rank-to-renderer recipes in the StarCi playbook; the Offset Pop stylesheet owns its family palette
|
|
296
296
|
and display treatment.
|
|
297
297
|
padding:
|
|
298
298
|
ownership: FE-RULE-OWNERSHIP
|
|
299
|
-
inherits:
|
|
299
|
+
inherits: core
|
|
300
300
|
contract: |
|
|
301
301
|
Offset Pop keeps the same Common spacing and component geometry. Its padding proof reads the
|
|
302
302
|
shared Common recipes declared in the StarCi playbook; it supplies no replacement inset scale.
|
|
@@ -21,7 +21,7 @@ pins:
|
|
|
21
21
|
install: registry
|
|
22
22
|
side: fe
|
|
23
23
|
source: packages/heroicons/package.json
|
|
24
|
-
why: 'StarCi custom Heroicons-compatible cuts; eslint-grammar-
|
|
24
|
+
why: 'StarCi custom Heroicons-compatible cuts; eslint-grammar-core (icon.mjs) admits @starci/heroicons/24/outline and /16/solid as icon sources, so an app that uses them gets this exact version.'
|
|
25
25
|
'@starci/event-stream':
|
|
26
26
|
version: 0.1.0
|
|
27
27
|
group: starci
|
|
@@ -30,61 +30,61 @@ pins:
|
|
|
30
30
|
source: packages/event-stream/package.json
|
|
31
31
|
why: 'the one server-sent-events client of every front end (fe-stack event-stream, owner:event-stream-package): the transport client layer (modules/api/sse/clients) creates one instance for the app with the bearer token source and the stream operations follow on it; it carries Last-Event-ID resume, the capped doubling backoff, the heartbeat timeout, the single 401 renewal and the useSWRSubscription adapter, so no app keeps a hand-written reader.'
|
|
32
32
|
'@starci/grammar':
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.13.0
|
|
34
34
|
group: starci
|
|
35
35
|
install: registry
|
|
36
36
|
side: fe
|
|
37
37
|
source: packages/grammar/package.json
|
|
38
38
|
why: 'the grammar front ends read: the brand layer sets `--font-sans` and `--font-mono` and the grammar reads them; it carries the Input tel kind, the copyable and read-only Input, the IconButton disclosure props and count badge, ChatBubble, FillViewport, Textarea mentions and Enter-to-send, the leading PrimaryRailLayout rail, the plate-less Image, ListRow, the soft Alert, Progress steps, the floating primary IconButton, FlowGraph, the STATE-8 loading views and the bordered selectable TagGroup chips. The runtime source version wins for a @starci package.'
|
|
39
39
|
'@starci/eslint-canon-be':
|
|
40
|
-
version: 3.4.
|
|
40
|
+
version: 3.4.57
|
|
41
41
|
group: starci
|
|
42
42
|
install: registry
|
|
43
43
|
side: be
|
|
44
|
-
source: packages/eslint
|
|
44
|
+
source: packages/eslint-canon-be/package.json
|
|
45
45
|
why: 'the back-end ESLint canon: `loadHfs(import.meta.url)` of be/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the be side, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; `starciBeConfig({ hfs: loadHfs(import.meta.url) })` is the typed factory and the BE-CONVENTION laws are its rules.'
|
|
46
46
|
'@starci/eslint-canon-fe':
|
|
47
|
-
version: 9.
|
|
47
|
+
version: 9.2.0
|
|
48
48
|
group: starci
|
|
49
49
|
install: registry
|
|
50
50
|
side: fe
|
|
51
|
-
source: packages/eslint
|
|
51
|
+
source: packages/eslint-canon-fe/package.json
|
|
52
52
|
why: 'the front-end ESLint canon: `loadHfs(import.meta.url)` of fe/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the fe side, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; the front end has no tests (FE_NO_TESTS R97 in hfs) and no-vietnamese-in-source (R91) applies.'
|
|
53
|
-
'@starci/eslint-grammar-
|
|
54
|
-
version: 0.
|
|
53
|
+
'@starci/eslint-grammar-core':
|
|
54
|
+
version: 0.13.0
|
|
55
55
|
group: starci
|
|
56
56
|
install: registry
|
|
57
57
|
side: fe
|
|
58
|
-
source: packages/eslint
|
|
58
|
+
source: packages/eslint-grammar-core/package.json
|
|
59
59
|
why: 'the StarCi Grammar component API lint, versioned with @starci/grammar; front ends compose this family package with the universal FE canon.'
|
|
60
60
|
'@starci/eslint-grammar-offset-pop':
|
|
61
|
-
version: 0.
|
|
61
|
+
version: 0.13.0
|
|
62
62
|
group: starci
|
|
63
63
|
install: registry
|
|
64
64
|
side: fe
|
|
65
|
-
source: packages/eslint
|
|
65
|
+
source: packages/eslint-grammar-offset-pop/package.json
|
|
66
66
|
why: 'the Offset Pop Grammar component API lint, versioned with @starci/grammar; its shared component contract comes from the StarCi family lint without copying rules.'
|
|
67
67
|
'@starci/stylelint-canon':
|
|
68
|
-
version: 2.0
|
|
68
|
+
version: 2.1.0
|
|
69
69
|
group: starci
|
|
70
70
|
install: registry
|
|
71
71
|
side: fe
|
|
72
|
-
source: packages/stylelint/package.json
|
|
72
|
+
source: packages/stylelint-canon/package.json
|
|
73
73
|
why: 'the front-end stylelint canon: no-class-selector refuses a compound class selector (`div.card`); the brand layer accepts `--font-sans` and `--font-mono`; status-contrast measures the HeroUI soft pairs per theme; brand-layer-shape reads the shared :root,.light,.dark block and the info soft pair; appTokens come from loadAppTokens(import.meta.url) for the managed one-line stylelint.config.mjs.'
|
|
74
74
|
'@starci/tsconfig':
|
|
75
|
-
version: 2.0.
|
|
75
|
+
version: 2.0.8
|
|
76
76
|
group: starci
|
|
77
77
|
install: registry
|
|
78
78
|
side: both
|
|
79
79
|
source: packages/tsconfig/package.json
|
|
80
80
|
'@starci/prettier-config':
|
|
81
|
-
version: 1.0.
|
|
81
|
+
version: 1.0.5
|
|
82
82
|
group: starci
|
|
83
83
|
install: registry
|
|
84
84
|
side: both
|
|
85
85
|
source: packages/prettier-config/package.json
|
|
86
86
|
'@starci/jest-preset':
|
|
87
|
-
version: 2.3.
|
|
87
|
+
version: 2.3.7
|
|
88
88
|
group: starci
|
|
89
89
|
install: registry
|
|
90
90
|
side: be
|
|
@@ -98,14 +98,13 @@ pins:
|
|
|
98
98
|
source: packages/test-world/package.json
|
|
99
99
|
why: 'the shared e2e library of every back end (R47, R48), a devDependency of every back end: the warm stack behind toxiproxy, the network-edge fakes, the Nest boot, the typed useTestWorld handle, useSandbox for contract specs and the outage lock. Kafka is real own infra (the one digest-pinned apache/kafka KRaft image, a broker listener and proxy per slot, slot-prefixed topics, consumer groups and client ids) and Postgres is schema-per-context (a schema and a login role per context in a shared database). Each worker has its own data slot (<ns>_w<k>) with its own databases, Keycloak realm, leased Redis DB, bucket/collection/topic prefixes, fakes host, toxiproxy proxies and outage lock; a run provisions min(jest workers, workers cap, default 2) slots, and state file protocol 2 pairs exactly with @starci/jest-preset (TEST_WORLD_PAIR_MISMATCH otherwise). A modules world boots real peer apps beside its modules, world.apps.<name>.during(fn) is the outage of a peer app, w.keycloak.clientSecret(client) answers the run-generated secret of a confidential realm client, world.keycloak.events/sessions read the realm user events and live sessions, world.infra.postgresql.connection(name) takes one database connection down while the others serve, and world.resolve and scope.resolve take any Nest token. Every path a declaration names (`stack`, seeds, the realm, Dockerfiles) resolves from the app root (the directory of hfs.json); the globalSetup registers the path aliases as TypeScript resolves them. Its CLI main is exported at ./cli for starci app stack.'
|
|
100
100
|
'@starci/cli':
|
|
101
|
-
version: 1.7.
|
|
101
|
+
version: 1.7.47
|
|
102
102
|
group: starci
|
|
103
103
|
install: registry
|
|
104
104
|
side: both
|
|
105
|
-
source: packages/cli/package.json
|
|
106
105
|
why: 'the only StarCi command package; product repositories install it for starci app, while @starci/hfs remains its pinned transitive implementation.'
|
|
107
106
|
'@starci/hfs':
|
|
108
|
-
version: 4.
|
|
107
|
+
version: 4.8.0
|
|
109
108
|
group: starci
|
|
110
109
|
install: registry
|
|
111
110
|
side: both
|
|
@@ -406,7 +405,7 @@ pins:
|
|
|
406
405
|
version: 2.2.0
|
|
407
406
|
group: ui
|
|
408
407
|
side: fe
|
|
409
|
-
why: 'the base of the one application icon set (fe-stack icons, with @starci/heroicons for the glyphs it lacks); eslint-grammar-
|
|
408
|
+
why: 'the base of the one application icon set (fe-stack icons, with @starci/heroicons for the glyphs it lacks); eslint-grammar-core (icon.mjs) admits @heroicons/react/24/outline and /16/solid.'
|
|
410
409
|
'@dicebear/core':
|
|
411
410
|
version: 10.4.0
|
|
412
411
|
group: ui
|
|
@@ -251,7 +251,7 @@ concerns:
|
|
|
251
251
|
why: the canon lint and format configuration.
|
|
252
252
|
- id: grammar-lint
|
|
253
253
|
tier: opt
|
|
254
|
-
packages: ['@starci/eslint-grammar-
|
|
254
|
+
packages: ['@starci/eslint-grammar-core', '@starci/eslint-grammar-offset-pop']
|
|
255
255
|
home: [fe.source-root-pinned]
|
|
256
256
|
pattern: FE-RULE-OWNERSHIP
|
|
257
257
|
forbids: []
|
|
@@ -29,7 +29,7 @@ gates:
|
|
|
29
29
|
enforcerKinds:
|
|
30
30
|
eslint-be: a rule of the plugin @starci/eslint-canon-be (id without the plugin prefix)
|
|
31
31
|
eslint-fe: a universal rule of @starci/eslint-canon-fe (id without the plugin prefix)
|
|
32
|
-
eslint-grammar-
|
|
32
|
+
eslint-grammar-core: a selected Grammar family rule sharing the common component API, resolved through the family canon binding (id without the plugin prefix; FE-RULE-OWNERSHIP)
|
|
33
33
|
stylelint: a rule of the @starci/stylelint-canon package
|
|
34
34
|
machine: a check of the architecture machine (scripts/hfs/architecture), which reads the import graph
|
|
35
35
|
hfs: a check of the hfs CLI that reads the repository tree, configuration, contracts or catalogs
|
|
@@ -1273,49 +1273,49 @@ rules:
|
|
|
1273
1273
|
- {kind: stylelint, id: breakpoint-scale}
|
|
1274
1274
|
- {kind: stylelint, id: source-resolves}
|
|
1275
1275
|
- {kind: eslint-fe, id: no-raw-brand-value}
|
|
1276
|
-
- {kind: eslint-grammar-
|
|
1276
|
+
- {kind: eslint-grammar-core, id: no-fractional-step}
|
|
1277
1277
|
- {kind: eslint-fe, id: no-arbitrary-value}
|
|
1278
|
-
- {kind: eslint-grammar-
|
|
1279
|
-
- {kind: eslint-grammar-
|
|
1280
|
-
- {kind: eslint-grammar-
|
|
1281
|
-
- {kind: eslint-grammar-
|
|
1278
|
+
- {kind: eslint-grammar-core, id: no-hand-rolled-heading}
|
|
1279
|
+
- {kind: eslint-grammar-core, id: no-unresolved-token-class}
|
|
1280
|
+
- {kind: eslint-grammar-core, id: no-heading-tag-outside-heading-component}
|
|
1281
|
+
- {kind: eslint-grammar-core, id: status-text-uses-soft-foreground}
|
|
1282
1282
|
proves:
|
|
1283
1283
|
- {path: packages/stylelint/source-resolves.spec.mjs, editions: [lite, full], codes: [FE_STYLE_SOURCE_UNRESOLVED]}
|
|
1284
1284
|
- {path: packages/eslint/fe/brand-values.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1285
1285
|
- {path: packages/eslint/fe/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1286
|
-
- {path: packages/eslint/grammar-
|
|
1287
|
-
- {path: packages/eslint/grammar-
|
|
1288
|
-
- {path: packages/eslint/grammar-
|
|
1286
|
+
- {path: packages/eslint/grammar-core/status-colors.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1287
|
+
- {path: packages/eslint/grammar-core/typography.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1288
|
+
- {path: packages/eslint/grammar-core/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1289
1289
|
exemplifiedBy:
|
|
1290
1290
|
- {path: packages/hfs/templates/fe/skeleton-lite/apps/web/src/app/globals.css, edition: lite}
|
|
1291
1291
|
- {path: packages/hfs/templates/fe/skeleton/apps/app/src/app/globals.css, edition: full}
|
|
1292
1292
|
- {path: packages/stylelint/source-resolves.spec.mjs, editions: [lite, full], codes: [FE_STYLE_SOURCE_UNRESOLVED]}
|
|
1293
1293
|
- {path: packages/eslint/fe/brand-values.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1294
1294
|
- {path: packages/eslint/fe/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1295
|
-
- {path: packages/eslint/grammar-
|
|
1296
|
-
- {path: packages/eslint/grammar-
|
|
1297
|
-
- {path: packages/eslint/grammar-
|
|
1295
|
+
- {path: packages/eslint/grammar-core/status-colors.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1296
|
+
- {path: packages/eslint/grammar-core/typography.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1297
|
+
- {path: packages/eslint/grammar-core/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1298
1298
|
witness:
|
|
1299
1299
|
- {path: packages/stylelint/source-resolves.spec.mjs, editions: [lite, full], codes: [FE_STYLE_SOURCE_UNRESOLVED]}
|
|
1300
1300
|
- {path: packages/eslint/fe/brand-values.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1301
1301
|
- {path: packages/eslint/fe/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1302
|
-
- {path: packages/eslint/grammar-
|
|
1303
|
-
- {path: packages/eslint/grammar-
|
|
1304
|
-
- {path: packages/eslint/grammar-
|
|
1302
|
+
- {path: packages/eslint/grammar-core/status-colors.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1303
|
+
- {path: packages/eslint/grammar-core/typography.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1304
|
+
- {path: packages/eslint/grammar-core/tokens.spec.mjs, editions: [lite, full], codes: [FE_STYLE_TOKEN_ONLY]}
|
|
1305
1305
|
- id: R62
|
|
1306
1306
|
code: "FE_NATIVE_FORM_CONTROL"
|
|
1307
1307
|
editions: [lite, full]
|
|
1308
1308
|
docs: [docs/architecture.md#r62, knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP]
|
|
1309
1309
|
proves:
|
|
1310
|
-
- {path: packages/eslint/grammar-
|
|
1310
|
+
- {path: packages/eslint/grammar-core/r62-structural-elements-coverage.spec.mjs, editions: [lite, full], codes: [FE_NATIVE_FORM_CONTROL]}
|
|
1311
1311
|
- {path: packages/eslint/fe/r62-native-controls-coverage.spec.mjs, editions: [lite, full]}
|
|
1312
1312
|
exemplifiedBy:
|
|
1313
|
-
- {path: packages/eslint/grammar-
|
|
1313
|
+
- {path: packages/eslint/grammar-core/r62-structural-elements-coverage.spec.mjs, editions: [lite, full], codes: [FE_NATIVE_FORM_CONTROL]}
|
|
1314
1314
|
- {path: packages/hfs/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx, edition: lite}
|
|
1315
1315
|
- {path: packages/hfs/templates/fe/skeleton/apps/__app__/src/components/blocks/SignInForm/component.tsx, edition: full}
|
|
1316
1316
|
- {path: packages/eslint/fe/r62-native-controls-coverage.spec.mjs, editions: [lite, full]}
|
|
1317
1317
|
witness:
|
|
1318
|
-
- {path: packages/eslint/grammar-
|
|
1318
|
+
- {path: packages/eslint/grammar-core/r62-structural-elements-coverage.spec.mjs, editions: [lite, full], codes: [FE_NATIVE_FORM_CONTROL]}
|
|
1319
1319
|
- {path: packages/eslint/fe/r62-native-controls-coverage.spec.mjs, edition: lite, codes: [FE_NATIVE_FORM_CONTROL, FE_NATIVE_IMAGE]}
|
|
1320
1320
|
- {path: packages/eslint/fe/r62-native-controls-coverage.spec.mjs, edition: full, codes: [FE_NATIVE_FORM_CONTROL, FE_NATIVE_IMAGE]}
|
|
1321
1321
|
law: "Product tiers compose the selected Grammar renderers for form controls, images and structural elements that the Grammar owns; they never reproduce those renderers with raw HTML."
|
|
@@ -1325,7 +1325,7 @@ rules:
|
|
|
1325
1325
|
enforcers:
|
|
1326
1326
|
- {kind: eslint-fe, id: no-native-form-control}
|
|
1327
1327
|
- {kind: eslint-fe, id: no-native-img}
|
|
1328
|
-
- {kind: eslint-grammar-
|
|
1328
|
+
- {kind: eslint-grammar-core, id: no-raw-structural-element}
|
|
1329
1329
|
- {kind: eslint-fe, id: image-has-size}
|
|
1330
1330
|
|
|
1331
1331
|
- id: R63
|
|
@@ -1878,7 +1878,7 @@ rules:
|
|
|
1878
1878
|
- {kind: eslint-fe, id: base-props-atom}
|
|
1879
1879
|
- {kind: eslint-fe, id: base-import-pair}
|
|
1880
1880
|
- {kind: eslint-fe, id: no-data-status-shape}
|
|
1881
|
-
- {kind: eslint-grammar-
|
|
1881
|
+
- {kind: eslint-grammar-core, id: slot-status-through-slotview}
|
|
1882
1882
|
- {kind: eslint-fe, id: presentational-purity}
|
|
1883
1883
|
- {kind: eslint-fe, id: connected-block-has-presentational-twin}
|
|
1884
1884
|
- {kind: eslint-fe, id: no-resting-twin-component}
|
|
@@ -1891,18 +1891,18 @@ rules:
|
|
|
1891
1891
|
editions: [lite, full]
|
|
1892
1892
|
docs: [docs/architecture.md#r92, knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP]
|
|
1893
1893
|
proves:
|
|
1894
|
-
- {path: packages/eslint/grammar-
|
|
1894
|
+
- {path: packages/eslint/grammar-core/r92-slot-status-coverage.spec.mjs, editions: [lite, full], codes: [FE_COMPONENT_API]}
|
|
1895
1895
|
- {path: packages/eslint/fe/r92-fetch-barrel.spec.mjs, editions: [lite, full]}
|
|
1896
1896
|
- {path: packages/eslint/fe/r92-component-surface-coverage.spec.mjs, editions: [lite, full]}
|
|
1897
1897
|
- {path: packages/eslint/fe/r56-r92-graph-coverage.spec.mjs, editions: [lite, full]}
|
|
1898
1898
|
exemplifiedBy:
|
|
1899
|
-
- {path: packages/eslint/grammar-
|
|
1899
|
+
- {path: packages/eslint/grammar-core/r92-slot-status-coverage.spec.mjs, editions: [lite, full], codes: [FE_COMPONENT_API]}
|
|
1900
1900
|
- {path: packages/hfs/templates/fe/skeleton/apps/__app__/src/components/blocks/SignInForm/component.tsx, editions: [lite, full]}
|
|
1901
1901
|
- {path: packages/eslint/fe/r92-fetch-barrel.spec.mjs, editions: [lite, full]}
|
|
1902
1902
|
- {path: packages/eslint/fe/r92-component-surface-coverage.spec.mjs, editions: [lite, full]}
|
|
1903
1903
|
- {path: packages/eslint/fe/r56-r92-graph-coverage.spec.mjs, editions: [lite, full]}
|
|
1904
1904
|
witness:
|
|
1905
|
-
- {path: packages/eslint/grammar-
|
|
1905
|
+
- {path: packages/eslint/grammar-core/r92-slot-status-coverage.spec.mjs, editions: [lite, full], codes: [FE_COMPONENT_API]}
|
|
1906
1906
|
- {path: packages/eslint/fe/r92-fetch-barrel.spec.mjs, editions: [lite, full]}
|
|
1907
1907
|
- {path: packages/eslint/fe/r92-component-surface-coverage.spec.mjs, editions: [lite, full]}
|
|
1908
1908
|
- {path: packages/eslint/fe/r56-r92-graph-coverage.spec.mjs, editions: [lite, full]}
|
|
@@ -1913,29 +1913,29 @@ rules:
|
|
|
1913
1913
|
gates: [pre-commit, settle, land, ci]
|
|
1914
1914
|
failureCodes: ["FE_VENDOR_BOUNDARY", "ARCH_GRAMMAR_CONTRACT_INVALID", "ARCH_GRAMMAR_EXPORT_BYPASS"]
|
|
1915
1915
|
enforcers:
|
|
1916
|
-
- {kind: eslint-grammar-
|
|
1917
|
-
- {kind: eslint-grammar-
|
|
1918
|
-
- {kind: eslint-grammar-
|
|
1919
|
-
- {kind: eslint-grammar-
|
|
1920
|
-
- {kind: eslint-grammar-
|
|
1921
|
-
- {kind: eslint-grammar-
|
|
1922
|
-
- {kind: eslint-grammar-
|
|
1916
|
+
- {kind: eslint-grammar-core, id: no-vendor-icon-outside-icon-leaf}
|
|
1917
|
+
- {kind: eslint-grammar-core, id: heroicons-is-the-glyph-vendor}
|
|
1918
|
+
- {kind: eslint-grammar-core, id: no-off-scale-glyph-size}
|
|
1919
|
+
- {kind: eslint-grammar-core, id: no-icon-size-class}
|
|
1920
|
+
- {kind: eslint-grammar-core, id: destructive-menu-entry-needs-danger-tone}
|
|
1921
|
+
- {kind: eslint-grammar-core, id: no-decorative-icon-in-metric-cell}
|
|
1922
|
+
- {kind: eslint-grammar-core, id: vendor-primitive-has-named-owner}
|
|
1923
1923
|
- {kind: eslint-fe, id: grammar-entry}
|
|
1924
1924
|
- {kind: machine, id: grammar, at: scripts/hfs/architecture/frontend-grammar.mjs}
|
|
1925
1925
|
editions: [lite, full]
|
|
1926
1926
|
docs: ["docs/code-pattern-enforcement.md#r93-vendor-and-grammar-ownership", knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP]
|
|
1927
1927
|
templateNa: "Vendor boundary violations and installed Grammar package contracts are checked against consumer ownership; no managed template scaffolds a vendor install or a forbidden import."
|
|
1928
1928
|
proves:
|
|
1929
|
-
- packages/eslint/grammar-
|
|
1929
|
+
- packages/eslint/grammar-core/r93-vendor-coverage.spec.mjs
|
|
1930
1930
|
- packages/eslint/fe/r93-grammar-ownership.spec.mjs
|
|
1931
|
-
- packages/eslint/grammar-
|
|
1931
|
+
- packages/eslint/grammar-core/menu-entries.spec.mjs
|
|
1932
1932
|
exemplifiedBy:
|
|
1933
|
-
- {path: packages/eslint/grammar-
|
|
1933
|
+
- {path: packages/eslint/grammar-core/r93-vendor-coverage.spec.mjs, editions: [lite, full]}
|
|
1934
1934
|
- {path: packages/eslint/fe/r93-grammar-ownership.spec.mjs, editions: [lite, full]}
|
|
1935
|
-
- {path: packages/eslint/grammar-
|
|
1935
|
+
- {path: packages/eslint/grammar-core/menu-entries.spec.mjs, editions: [lite, full]}
|
|
1936
1936
|
witness:
|
|
1937
|
-
- {path: packages/eslint/grammar-
|
|
1938
|
-
- {path: packages/eslint/grammar-
|
|
1937
|
+
- {path: packages/eslint/grammar-core/menu-entries.spec.mjs, editions: [lite, full], codes: [FE_VENDOR_BOUNDARY]}
|
|
1938
|
+
- {path: packages/eslint/grammar-core/r93-vendor-coverage.spec.mjs, editions: [lite, full], codes: [FE_VENDOR_BOUNDARY]}
|
|
1939
1939
|
- {path: packages/eslint/fe/r93-grammar-ownership.spec.mjs, editions: [lite, full], codes: [ARCH_GRAMMAR_CONTRACT_INVALID, ARCH_GRAMMAR_EXPORT_BYPASS]}
|
|
1940
1940
|
- id: R94
|
|
1941
1941
|
code: "FE_SLOT_FILE_ROLE"
|
|
@@ -5006,20 +5006,20 @@ rules:
|
|
|
5006
5006
|
enforcers:
|
|
5007
5007
|
- {kind: eslint-fe, id: no-copy-in-call}
|
|
5008
5008
|
- {kind: eslint-fe, id: no-alert}
|
|
5009
|
-
- {kind: eslint-grammar-
|
|
5009
|
+
- {kind: eslint-grammar-core, id: no-inline-svg-outside-brand-mark-leaf}
|
|
5010
5010
|
editions: [lite, full]
|
|
5011
5011
|
docs: [docs/quality-bar.md#r286, knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP]
|
|
5012
5012
|
exemplifiedBy:
|
|
5013
5013
|
- {path: packages/eslint/fe/translation.spec.mjs, editions: [lite, full], codes: [FE_COPY_IN_CALL, FE_NO_ALERT]}
|
|
5014
|
-
- {path: packages/eslint/grammar-
|
|
5014
|
+
- {path: packages/eslint/grammar-core/icon.spec.mjs, editions: [lite, full], codes: [FE_ICON_INLINE_SVG]}
|
|
5015
5015
|
- {path: packages/hfs/templates/fe/skeleton/apps/__app__/src/components/leaves/Icon/index.tsx, editions: [lite, full]}
|
|
5016
5016
|
- {path: packages/hfs/templates/fe/skeleton/apps/__app__/src/modules/toast, editions: [lite, full]}
|
|
5017
5017
|
proves:
|
|
5018
5018
|
- {path: packages/eslint/fe/translation.spec.mjs, editions: [lite, full], codes: [FE_COPY_IN_CALL, FE_NO_ALERT]}
|
|
5019
|
-
- {path: packages/eslint/grammar-
|
|
5019
|
+
- {path: packages/eslint/grammar-core/icon.spec.mjs, editions: [lite, full], codes: [FE_ICON_INLINE_SVG]}
|
|
5020
5020
|
witness:
|
|
5021
5021
|
- {path: packages/eslint/fe/translation.spec.mjs, editions: [lite, full], codes: [FE_COPY_IN_CALL, FE_NO_ALERT]}
|
|
5022
|
-
- {path: packages/eslint/grammar-
|
|
5022
|
+
- {path: packages/eslint/grammar-core/icon.spec.mjs, editions: [lite, full], codes: [FE_ICON_INLINE_SVG]}
|
|
5023
5023
|
|
|
5024
5024
|
- id: R287
|
|
5025
5025
|
code: "FE_CALLBACK_SHAPE"
|
|
@@ -5476,19 +5476,19 @@ rules:
|
|
|
5476
5476
|
gates: [pre-commit, settle, land, ci]
|
|
5477
5477
|
failureCodes: ["FE_APP_SHELL_FRAME"]
|
|
5478
5478
|
enforcers:
|
|
5479
|
-
- {kind: eslint-grammar-
|
|
5479
|
+
- {kind: eslint-grammar-core, id: app-shell-frame}
|
|
5480
5480
|
editions: [lite, full]
|
|
5481
5481
|
docs:
|
|
5482
5482
|
- knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP
|
|
5483
5483
|
- {path: knowledge/ui/composition/app-shell.yaml, editions: [lite, full]}
|
|
5484
5484
|
proves:
|
|
5485
|
-
- {path: packages/eslint/grammar-
|
|
5485
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_FRAME]}
|
|
5486
5486
|
exemplifiedBy:
|
|
5487
|
-
- {path: packages/eslint/grammar-
|
|
5487
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_FRAME]}
|
|
5488
5488
|
- {path: examples/full-app/fe/apps/app/src/features/layouts/ShopLayout/component.tsx, edition: full}
|
|
5489
5489
|
- {path: examples/lite-app/fe/apps/web/src/features/layouts/WorkspaceLayout/component.tsx, edition: lite}
|
|
5490
5490
|
witness:
|
|
5491
|
-
- {path: packages/eslint/grammar-
|
|
5491
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_FRAME]}
|
|
5492
5492
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5493
5493
|
- id: R314
|
|
5494
5494
|
code: "FE_NAVBAR_CONTROL_SIZE"
|
|
@@ -5497,19 +5497,19 @@ rules:
|
|
|
5497
5497
|
gates: [pre-commit, settle, land, ci]
|
|
5498
5498
|
failureCodes: ["FE_NAVBAR_CONTROL_SIZE"]
|
|
5499
5499
|
enforcers:
|
|
5500
|
-
- {kind: eslint-grammar-
|
|
5500
|
+
- {kind: eslint-grammar-core, id: navbar-control-size}
|
|
5501
5501
|
editions: [lite, full]
|
|
5502
5502
|
docs:
|
|
5503
5503
|
- knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP
|
|
5504
5504
|
- {path: knowledge/ui/composition/app-shell.yaml, editions: [lite, full]}
|
|
5505
5505
|
proves:
|
|
5506
|
-
- {path: packages/eslint/grammar-
|
|
5506
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CONTROL_SIZE]}
|
|
5507
5507
|
exemplifiedBy:
|
|
5508
|
-
- {path: packages/eslint/grammar-
|
|
5508
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CONTROL_SIZE]}
|
|
5509
5509
|
- {path: examples/full-app/fe/packages/ecommerce-ui/src/branches/WorkspaceNavbar/component.tsx, edition: full}
|
|
5510
5510
|
- {path: examples/lite-app/fe/apps/web/src/components/branches/Navbar/component.tsx, edition: lite}
|
|
5511
5511
|
witness:
|
|
5512
|
-
- {path: packages/eslint/grammar-
|
|
5512
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CONTROL_SIZE]}
|
|
5513
5513
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5514
5514
|
- id: R315
|
|
5515
5515
|
code: "FE_NAVBAR_CLUSTER"
|
|
@@ -5518,19 +5518,19 @@ rules:
|
|
|
5518
5518
|
gates: [pre-commit, settle, land, ci]
|
|
5519
5519
|
failureCodes: ["FE_NAVBAR_CLUSTER"]
|
|
5520
5520
|
enforcers:
|
|
5521
|
-
- {kind: eslint-grammar-
|
|
5521
|
+
- {kind: eslint-grammar-core, id: navbar-cluster}
|
|
5522
5522
|
editions: [lite, full]
|
|
5523
5523
|
docs:
|
|
5524
5524
|
- knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP
|
|
5525
5525
|
- {path: knowledge/ui/composition/app-shell.yaml, editions: [lite, full]}
|
|
5526
5526
|
proves:
|
|
5527
|
-
- {path: packages/eslint/grammar-
|
|
5527
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CLUSTER]}
|
|
5528
5528
|
exemplifiedBy:
|
|
5529
|
-
- {path: packages/eslint/grammar-
|
|
5529
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CLUSTER]}
|
|
5530
5530
|
- {path: examples/full-app/fe/packages/ecommerce-ui/src/branches/WorkspaceNavbar/component.tsx, edition: full}
|
|
5531
5531
|
- {path: examples/lite-app/fe/apps/web/src/components/branches/Navbar/component.tsx, edition: lite}
|
|
5532
5532
|
witness:
|
|
5533
|
-
- {path: packages/eslint/grammar-
|
|
5533
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CLUSTER]}
|
|
5534
5534
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5535
5535
|
- id: R316
|
|
5536
5536
|
code: "FE_APP_SHELL_BOTTOM_TABS"
|
|
@@ -5539,19 +5539,19 @@ rules:
|
|
|
5539
5539
|
gates: [pre-commit, settle, land, ci]
|
|
5540
5540
|
failureCodes: ["FE_APP_SHELL_BOTTOM_TABS"]
|
|
5541
5541
|
enforcers:
|
|
5542
|
-
- {kind: eslint-grammar-
|
|
5542
|
+
- {kind: eslint-grammar-core, id: no-shell-bottom-tabs}
|
|
5543
5543
|
editions: [lite, full]
|
|
5544
5544
|
docs:
|
|
5545
5545
|
- knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP
|
|
5546
5546
|
- {path: knowledge/ui/composition/app-shell.yaml, editions: [lite, full]}
|
|
5547
5547
|
proves:
|
|
5548
|
-
- {path: packages/eslint/grammar-
|
|
5548
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_BOTTOM_TABS]}
|
|
5549
5549
|
exemplifiedBy:
|
|
5550
|
-
- {path: packages/eslint/grammar-
|
|
5550
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_BOTTOM_TABS]}
|
|
5551
5551
|
- {path: examples/full-app/fe/apps/app/src/features/layouts/ShopLayout/component.tsx, edition: full}
|
|
5552
5552
|
- {path: examples/lite-app/fe/apps/web/src/features/layouts/WorkspaceLayout/component.tsx, edition: lite}
|
|
5553
5553
|
witness:
|
|
5554
|
-
- {path: packages/eslint/grammar-
|
|
5554
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_APP_SHELL_BOTTOM_TABS]}
|
|
5555
5555
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5556
5556
|
- id: R317
|
|
5557
5557
|
code: "FE_NAVBAR_CREATE"
|
|
@@ -5560,19 +5560,19 @@ rules:
|
|
|
5560
5560
|
gates: [pre-commit, settle, land, ci]
|
|
5561
5561
|
failureCodes: ["FE_NAVBAR_CREATE"]
|
|
5562
5562
|
enforcers:
|
|
5563
|
-
- {kind: eslint-grammar-
|
|
5563
|
+
- {kind: eslint-grammar-core, id: no-navbar-create}
|
|
5564
5564
|
editions: [lite, full]
|
|
5565
5565
|
docs:
|
|
5566
5566
|
- knowledge/patterns/fe/index.yaml#FE-RULE-OWNERSHIP
|
|
5567
5567
|
- {path: knowledge/ui/composition/app-shell.yaml, editions: [lite, full]}
|
|
5568
5568
|
proves:
|
|
5569
|
-
- {path: packages/eslint/grammar-
|
|
5569
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CREATE]}
|
|
5570
5570
|
exemplifiedBy:
|
|
5571
|
-
- {path: packages/eslint/grammar-
|
|
5571
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CREATE]}
|
|
5572
5572
|
- {path: examples/full-app/fe/packages/ecommerce-ui/src/branches/WorkspaceNavbar/component.tsx, edition: full}
|
|
5573
5573
|
- {path: examples/lite-app/fe/apps/web/src/components/branches/Navbar/component.tsx, edition: lite}
|
|
5574
5574
|
witness:
|
|
5575
|
-
- {path: packages/eslint/grammar-
|
|
5575
|
+
- {path: packages/eslint/grammar-core/app-shell.spec.mjs, editions: [lite, full], codes: [FE_NAVBAR_CREATE]}
|
|
5576
5576
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5577
5577
|
- id: R318
|
|
5578
5578
|
code: "FE_NESTED_VARIANT"
|
|
@@ -2130,7 +2130,7 @@ FE_APP_SHELL_BOTTOM_TABS:
|
|
|
2130
2130
|
meaning_vi: "Khung ứng dụng tại <file> đặt điều hướng trong thanh tab dưới thay vì Sidebar drawer."
|
|
2131
2131
|
causes_vi:
|
|
2132
2132
|
- "Cấu trúc shell không theo canon ứng dụng."
|
|
2133
|
-
nextStep_vi: "Dùng hàng mở drawer bên dưới navbar và Sidebar presentation=\"drawer\" (R316; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2133
|
+
nextStep_vi: "Dùng hàng mở drawer bên dưới navbar và Sidebar presentation=\"drawer\" (R316; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2134
2134
|
owner: op-retry
|
|
2135
2135
|
kind: check-finding
|
|
2136
2136
|
|
|
@@ -2140,7 +2140,7 @@ FE_APP_SHELL_FRAME:
|
|
|
2140
2140
|
meaning_vi: "Khung ứng dụng tại <file> không giao bố cục và cuộn cho WorkspaceShell."
|
|
2141
2141
|
causes_vi:
|
|
2142
2142
|
- "Cấu trúc shell không theo canon ứng dụng."
|
|
2143
|
-
nextStep_vi: "Ghép khung ứng dụng bằng WorkspaceShell viewport=\"fixed\" (R313; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2143
|
+
nextStep_vi: "Ghép khung ứng dụng bằng WorkspaceShell viewport=\"fixed\" (R313; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2144
2144
|
owner: op-retry
|
|
2145
2145
|
kind: check-finding
|
|
2146
2146
|
|
|
@@ -2237,7 +2237,7 @@ FE_COMPONENT_API:
|
|
|
2237
2237
|
- "Component nhận className từ ngoài"
|
|
2238
2238
|
- "Khối kết nối không có bản trình bày thuần"
|
|
2239
2239
|
- "Trạng thái dữ liệu tự chế thay vì qua SlotView"
|
|
2240
|
-
nextStep_vi: "Sửa chữ ký component theo luật drawing và tách phần trình bày; op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra (R92; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2240
|
+
nextStep_vi: "Sửa chữ ký component theo luật drawing và tách phần trình bày; op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra (R92; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2241
2241
|
owner: op-retry
|
|
2242
2242
|
kind: check-finding
|
|
2243
2243
|
|
|
@@ -2530,7 +2530,7 @@ FE_ICON_INLINE_SVG:
|
|
|
2530
2530
|
causes_vi:
|
|
2531
2531
|
- "Leaf Icon tự vẽ path hoặc SVG thay vì dùng Heroicons"
|
|
2532
2532
|
- "Component vẽ SVG trực tiếp mà không phải leaf nhãn hiệu được khai báo"
|
|
2533
|
-
nextStep_vi: "Thay glyph bằng Heroicons qua leaf Icon; nếu là nhãn hiệu, đặt nó trong leaf nhãn hiệu và khai báo đúng chủ của leaf (R286; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2533
|
+
nextStep_vi: "Thay glyph bằng Heroicons qua leaf Icon; nếu là nhãn hiệu, đặt nó trong leaf nhãn hiệu và khai báo đúng chủ của leaf (R286; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2534
2534
|
owner: op-retry
|
|
2535
2535
|
kind: check-finding
|
|
2536
2536
|
|
|
@@ -2561,7 +2561,7 @@ FE_NATIVE_FORM_CONTROL:
|
|
|
2561
2561
|
meaning_vi: "`<tag>` thô ở `<file>`. Dùng renderer của grammar."
|
|
2562
2562
|
causes_vi:
|
|
2563
2563
|
- "Vi phạm luật R62: Không `<select>/<input>/<textarea>/<button>`, `<img>` thô và không thẻ cấu trúc thô (`<section>`, `<p>`, `<ul>`, `<h1>`...) ở tầng sản phẩm; dùng renderer grammar."
|
|
2564
|
-
nextStep_vi: "Op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra và mục của luật trong tiêu chuẩn HFS; nợ cũ cần quyết định thiết kế nên op không thêm ngoại lệ, chỉ tách hoặc chuyển về đúng chủ (R62; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2564
|
+
nextStep_vi: "Op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra và mục của luật trong tiêu chuẩn HFS; nợ cũ cần quyết định thiết kế nên op không thêm ngoại lệ, chỉ tách hoặc chuyển về đúng chủ (R62; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2565
2565
|
owner: op-retry
|
|
2566
2566
|
kind: check-finding
|
|
2567
2567
|
|
|
@@ -2581,7 +2581,7 @@ FE_NAVBAR_CLUSTER:
|
|
|
2581
2581
|
meaning_vi: "Cụm navbar tại <file> không giữ thứ tự ngôn ngữ, giao diện, thông báo và tài khoản."
|
|
2582
2582
|
causes_vi:
|
|
2583
2583
|
- "Cấu trúc shell không theo canon ứng dụng."
|
|
2584
|
-
nextStep_vi: "Ghép IconButton ngôn ngữ, Switch giao diện, IconButton chuông và AvatarButton theo đúng thứ tự (R315; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2584
|
+
nextStep_vi: "Ghép IconButton ngôn ngữ, Switch giao diện, IconButton chuông và AvatarButton theo đúng thứ tự (R315; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2585
2585
|
owner: op-retry
|
|
2586
2586
|
kind: check-finding
|
|
2587
2587
|
|
|
@@ -2591,7 +2591,7 @@ FE_NAVBAR_CONTROL_SIZE:
|
|
|
2591
2591
|
meaning_vi: "Điều khiển trong navbar tại <file> không khai báo cùng cỡ control của Grammar."
|
|
2592
2592
|
causes_vi:
|
|
2593
2593
|
- "Cấu trúc shell không theo canon ứng dụng."
|
|
2594
|
-
nextStep_vi: "Đặt size=\"control\" trên từng điều khiển trong thanh (R314; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2594
|
+
nextStep_vi: "Đặt size=\"control\" trên từng điều khiển trong thanh (R314; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2595
2595
|
owner: op-retry
|
|
2596
2596
|
kind: check-finding
|
|
2597
2597
|
|
|
@@ -2601,7 +2601,7 @@ FE_NAVBAR_CREATE:
|
|
|
2601
2601
|
meaning_vi: "Navbar tại <file> chứa thao tác tạo mới thuộc nội dung trang."
|
|
2602
2602
|
causes_vi:
|
|
2603
2603
|
- "Cấu trúc shell không theo canon ứng dụng."
|
|
2604
|
-
nextStep_vi: "Đưa thao tác tạo mới về trang sở hữu nó (R317; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
2604
|
+
nextStep_vi: "Đưa thao tác tạo mới về trang sở hữu nó (R317; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
2605
2605
|
owner: op-retry
|
|
2606
2606
|
kind: check-finding
|
|
2607
2607
|
|
|
@@ -2953,8 +2953,8 @@ FE_STACK_FAMILY_LINT_MISSING:
|
|
|
2953
2953
|
title_vi: "Front end dùng canon-fe 9 nhưng thiếu gói lint của họ Grammar đã chọn"
|
|
2954
2954
|
meaning_vi: "hfs.json chọn sides.fe.grammar (starci hoặc offset-pop) và front end khai báo @starci/eslint-canon-fe 9 trở lên, nhưng không manifest nào khai báo gói lint của họ đó; từ canon-fe 9 các luật component Grammar nằm trong gói này, thiếu gói thì các luật ấy không chạy."
|
|
2955
2955
|
causes_vi:
|
|
2956
|
-
- "Nâng @starci/eslint-canon-fe lên 9 mà chưa thêm @starci/eslint-grammar-
|
|
2957
|
-
nextStep_vi: "Thêm @starci/eslint-grammar-
|
|
2956
|
+
- "Nâng @starci/eslint-canon-fe lên 9 mà chưa thêm @starci/eslint-grammar-core (Grammar StarCi) hoặc @starci/eslint-grammar-offset-pop (Grammar Offset Pop)."
|
|
2957
|
+
nextStep_vi: "Thêm @starci/eslint-grammar-core (hoặc @starci/eslint-grammar-offset-pop) cạnh @starci/eslint-canon-fe, ghép coreGrammarConfig({ hfs }) (hoặc offsetPopGrammarConfig({ hfs })) sau starciFeConfig({ hfs }) trong fe/eslint.config.mjs, hoặc chạy starci app sync."
|
|
2958
2958
|
owner: op-retry
|
|
2959
2959
|
kind: check-finding
|
|
2960
2960
|
|
|
@@ -3011,7 +3011,7 @@ FE_STYLE_TOKEN_ONLY:
|
|
|
3011
3011
|
- "@media dùng breakpoint ngoài thang của grammar"
|
|
3012
3012
|
- "brand.css thiếu cặp mềm của một tông trạng thái ở sáng hoặc tối, chữ mềm dưới 3:1 trên nền nhạt hoặc nền trang, --foreground dưới 4.5:1, hoặc giá trị màu không phân giải được"
|
|
3013
3013
|
- "Component tô chữ hoặc icon bằng text-success, text-danger, fill-warning, stroke-info (tông đặc) thay vì text-<tông>-soft-foreground"
|
|
3014
|
-
nextStep_vi: "Op interface.implement bỏ CSS riêng, dùng component và token của grammar; giá trị màu thương hiệu chỉ khai ở modules/brand/brand.css cho cả sáng và tối, đủ cặp mềm cho mọi tông trạng thái; chữ và icon trạng thái dùng text-<tông>-soft-foreground (R61; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
3014
|
+
nextStep_vi: "Op interface.implement bỏ CSS riêng, dùng component và token của grammar; giá trị màu thương hiệu chỉ khai ở modules/brand/brand.css cho cả sáng và tối, đủ cặp mềm cho mọi tông trạng thái; chữ và icon trạng thái dùng text-<tông>-soft-foreground (R61; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
3015
3015
|
owner: other-op:interface.implement
|
|
3016
3016
|
kind: check-finding
|
|
3017
3017
|
|
|
@@ -3130,7 +3130,7 @@ FE_VENDOR_BOUNDARY:
|
|
|
3130
3130
|
- "Dùng bộ glyph thứ hai ngoài họ heroicons (Phosphor, Lucide, Iconify...)"
|
|
3131
3131
|
- "Dùng kích thước biểu tượng ngoài thang"
|
|
3132
3132
|
- "Primitive thư viện ngoài dùng trực tiếp ở nhiều nơi"
|
|
3133
|
-
nextStep_vi: "Dùng lá icon và chủ sở hữu primitive có sẵn; op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra (R93; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-
|
|
3133
|
+
nextStep_vi: "Dùng lá icon và chủ sở hữu primitive có sẵn; op vừa tạo ra bản này sẽ được chạy lại để sửa theo lời nhắn của bộ kiểm tra (R93; FE-RULE-OWNERSHIP: knowledge/patterns/fe/index.yaml; packages/eslint/grammar-core/README.md)."
|
|
3134
3134
|
owner: op-retry
|
|
3135
3135
|
kind: check-finding
|
|
3136
3136
|
|
|
@@ -5007,7 +5007,7 @@ RT_GENERATED_BLOCK_STALE:
|
|
|
5007
5007
|
RT_GENERATED_DRIFT:
|
|
5008
5008
|
title: "Generated copy drifted"
|
|
5009
5009
|
title_vi: "Bản sao sinh tự động bị lệch"
|
|
5010
|
-
meaning_vi: "Một bản sao sinh tự động trong packages/hfs/runtime, packages/eslint/be/runtime hoặc packages/eslint/fe/runtime, packages/eslint/grammar-
|
|
5010
|
+
meaning_vi: "Một bản sao sinh tự động trong packages/hfs/runtime, packages/eslint/be/runtime hoặc packages/eslint/fe/runtime, packages/eslint/grammar-core/runtime, packages/eslint/grammar-offset-pop/runtime khác với nội dung mà scripts/hfs/sync-runtime.mjs ghi ra từ nguồn duy nhất: thiếu, cũ, hoặc thừa tệp."
|
|
5011
5011
|
causes_vi:
|
|
5012
5012
|
- "Sửa một tệp nguồn được đóng gói mà quên chạy sync-runtime"
|
|
5013
5013
|
- "Sửa tay một tệp trong thư mục runtime/ của gói"
|
|
@@ -12,7 +12,7 @@ import { fail } from './slot-errors.mjs';
|
|
|
12
12
|
|
|
13
13
|
const HFS_RULES_FILE = 'knowledge/hfs/rules.yaml';
|
|
14
14
|
const RULE_GATES = Object.freeze(['pre-commit', 'pre-push', 'settle', 'land', 'ci', 'sonar', 'runtime']);
|
|
15
|
-
const ENFORCER_FAMILIES = Object.freeze(['eslint-be', 'eslint-fe', 'eslint-grammar-
|
|
15
|
+
const ENFORCER_FAMILIES = Object.freeze(['eslint-be', 'eslint-fe', 'eslint-grammar-core', 'stylelint', 'machine', 'hfs', 'work-validate', 'sonar', 'runtime']);
|
|
16
16
|
const RULE_KINDS = Object.freeze(['codemod', 'lint', 'check', 'design']);
|
|
17
17
|
const FINDING_CODE = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$/;
|
|
18
18
|
const ENFORCER_ID = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
@@ -346,7 +346,7 @@ export function loadRuleCatalog({ root = skillRoot, file = path.join(root, HFS_R
|
|
|
346
346
|
/** The catalogued why code of a lint finding's rule id (`starci-be/<id>`, `starci-fe/<id>`), or undefined. */
|
|
347
347
|
lintCode: (ruleId) => {
|
|
348
348
|
const [plugin, id] = String(ruleId ?? '').split('/');
|
|
349
|
-
const kind = (plugin === 'starci-be' && 'eslint-be') || (plugin === 'starci-fe' && 'eslint-fe') || (plugin === 'starci-grammar' && 'eslint-grammar-
|
|
349
|
+
const kind = (plugin === 'starci-be' && 'eslint-be') || (plugin === 'starci-fe' && 'eslint-fe') || (plugin === 'starci-grammar' && 'eslint-grammar-core') || null;
|
|
350
350
|
return kind ? list.find((rule) => rule.enforcers.some((enforcer) => enforcer.kind === kind && enforcer.id === id))?.code : undefined;
|
|
351
351
|
},
|
|
352
352
|
/** The rules one enforcer judges, e.g. forEnforcer('eslint-be', 'error-home'). */
|
|
@@ -10,6 +10,7 @@ import path from 'node:path';
|
|
|
10
10
|
import { parseYaml } from '../../engine/yaml.mjs';
|
|
11
11
|
import { validateAgainstSchema } from './json-schema.mjs';
|
|
12
12
|
import { insidePath, samePath, slash } from './path-key.mjs';
|
|
13
|
+
import { resolveGrammarFamily } from './grammar-lint.mjs';
|
|
13
14
|
import { byCodeUnit } from './list.mjs';
|
|
14
15
|
import { isLiteWorkRoot, workPathAllowed } from './work-edition.mjs';
|
|
15
16
|
import { WORK_DIR_NAME } from './roots.mjs';
|
|
@@ -49,9 +50,15 @@ export const REFERENCE_APP_MANIFEST = `${EXAMPLES_ROOT}/full-app/hfs.json`;
|
|
|
49
50
|
/** The example app whose installed tree an fe-kit peer link points at by default. */
|
|
50
51
|
export const REFERENCE_EXAMPLE_APP = 'full-app';
|
|
51
52
|
|
|
52
|
-
/** The grammar css families a product repository may declare (`[data-grammar-family="<id>"]`)
|
|
53
|
-
* runtime's own product maps to the core sheet. */
|
|
54
|
-
export const GRAMMAR_FAMILIES = Object.freeze({
|
|
53
|
+
/** The grammar css families a product repository may declare (`[data-grammar-family="<id>"]`), keyed by the
|
|
54
|
+
* canonical catalog id; the runtime's own product maps to the core sheet. */
|
|
55
|
+
export const GRAMMAR_FAMILIES = Object.freeze({ core: 'core', nivo: 'nivo', 'offset-pop': 'offset-pop' });
|
|
56
|
+
|
|
57
|
+
/** A css family key through the Grammar catalog's alias table (`starci` reads as `core`); an id the catalog does not declare is kept. */
|
|
58
|
+
export function grammarCssFamilyKey(family) {
|
|
59
|
+
if (typeof family !== 'string' || !family) return family;
|
|
60
|
+
try { return resolveGrammarFamily(family).id; } catch { return family; }
|
|
61
|
+
}
|
|
55
62
|
|
|
56
63
|
/** A feature-folder segment that is only the product's own name - no useful leaf (display-names pathLabel). */
|
|
57
64
|
export const PRODUCT_NAME_SEGMENT = /^(nivo|starci|mia)[-\w]*$/i;
|
|
@@ -4,14 +4,27 @@ import { parseYamlCached } from './yaml-cached.mjs';
|
|
|
4
4
|
|
|
5
5
|
const CATALOG_FILE = new URL('../../knowledge/grammars/index.yaml', import.meta.url);
|
|
6
6
|
|
|
7
|
+
function readCatalog() {
|
|
8
|
+
return parseYamlCached(fs.readFileSync(CATALOG_FILE, 'utf8'));
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
function selectedFamily(family) {
|
|
8
12
|
if (typeof family !== 'string' || !family.trim()) throw new Error('sides.fe.grammar must explicitly name the selected Grammar family');
|
|
9
|
-
const catalog =
|
|
13
|
+
const catalog = readCatalog();
|
|
10
14
|
const matches = (catalog.families ?? []).filter(entry => entry.id === family);
|
|
11
15
|
if (matches.length !== 1) throw new Error(`Grammar family ${family} has no declared lint contract in knowledge/grammars/index.yaml`);
|
|
12
16
|
return { catalog, selected: matches[0] };
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a selection to its declared family id; only a catalog family id resolves, there are no aliases.
|
|
21
|
+
* @param {string} family - The id an app or caller names (sides.fe.grammar).
|
|
22
|
+
* @returns {{ id: string }} The declared family id.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveGrammarFamily(family) {
|
|
25
|
+
return Object.freeze({ id: selectedFamily(family).selected.id });
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
/** The explicitly selected authored family entry; callers share the catalog lookup rather than inferring a family. */
|
|
16
29
|
export function grammarFamilyFor(family) {
|
|
17
30
|
return Object.freeze(selectedFamily(family).selected);
|
|
@@ -24,13 +37,13 @@ export function grammarLintFor(family) {
|
|
|
24
37
|
throw new Error(`Grammar family ${family} has no declared lint contract in knowledge/grammars/index.yaml`);
|
|
25
38
|
}
|
|
26
39
|
const lint = selected.lint;
|
|
27
|
-
if (lint.package === null) return Object.freeze({ family, package: null });
|
|
40
|
+
if (lint.package === null) return Object.freeze({ family: selected.id, package: null });
|
|
28
41
|
if (typeof lint.package !== 'string' || !lint.package.startsWith('@starci/eslint-grammar-')
|
|
29
42
|
|| typeof lint.factory !== 'string' || !/^[a-zA-Z][a-zA-Z0-9]*$/.test(lint.factory)
|
|
30
43
|
|| typeof lint.prefix !== 'string' || !/^[a-z][a-z0-9-]*$/.test(lint.prefix)) {
|
|
31
44
|
throw new Error(`Grammar family ${family} has an invalid lint contract in knowledge/grammars/index.yaml`);
|
|
32
45
|
}
|
|
33
|
-
return Object.freeze({ family, package: lint.package, factory: lint.factory, prefix: lint.prefix });
|
|
46
|
+
return Object.freeze({ family: selected.id, package: lint.package, factory: lint.factory, prefix: lint.prefix });
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
/** The selected family's shared component/export contract, resolved through its catalog reference. */
|
package/scaffold/app.mjs
CHANGED
|
@@ -127,7 +127,7 @@ export const packageJsonText = value => `${JSON.stringify(value, null, 2)}\n`;
|
|
|
127
127
|
const STARTER_SIDES = Object.freeze({
|
|
128
128
|
be: Object.freeze({ apps: [{ name: 'core', kind: 'api' }, { name: 'cli', kind: 'cli' }], kinds: ['api', 'cli'], connections: [{ name: 'primary', envPrefix: 'PRIMARY_DB', owner: 'core', isolation: 'database' }] }),
|
|
129
129
|
// fe: the landing and the product app, over the shared ui and i18n packages (both opt-in slots, enabled here).
|
|
130
|
-
fe: Object.freeze({ grammar: '
|
|
130
|
+
fe: Object.freeze({ grammar: 'core', apps: [{ name: 'landing', kind: 'next' }, { name: 'app', kind: 'next' }], reads: ['be/contracts/'], optionalSlots: ['fe.package.ui', 'fe.package.i18n'] }),
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
/** The lite starter is the upgrade-safe subset: one API, one web app and one Supabase schema authority. */
|
|
@@ -138,7 +138,7 @@ const LITE_STARTER_SIDES = Object.freeze({
|
|
|
138
138
|
connections: [{ name: 'primary', envPrefix: 'PRIMARY_DB', owner: 'api', isolation: 'schema', provider: 'supabase' }],
|
|
139
139
|
reads: ['supabase/types/'],
|
|
140
140
|
}),
|
|
141
|
-
fe: Object.freeze({ grammar: '
|
|
141
|
+
fe: Object.freeze({ grammar: 'core', apps: [{ name: 'web', kind: 'next' }], reads: ['be/contracts/', 'supabase/types/'] }),
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
/** The checked local Supabase auth posture of every newly scaffolded lite app. */
|
package/stack/render.mjs
CHANGED
|
@@ -111,7 +111,9 @@ function dockerRender(ctx, config, overrideFile, options, env) {
|
|
|
111
111
|
if (run.error) throw failure('STACK_RENDER_FAILED', `cannot run docker (${run.error.message})`);
|
|
112
112
|
if (run.status !== 0) throw failure('STACK_RENDER_FAILED', run.stderr.trim().split('\n').slice(0, 6).join(' | '));
|
|
113
113
|
if (hasPlaceholderDigest(run.stdout)) throw refusal('STACK_PLACEHOLDER_DIGEST', 'rendered stack still carries a placeholder digest');
|
|
114
|
-
|
|
114
|
+
// docker stack config has already interpolated every variable, so a dollar left in its output is literal (a source `$`); docker stack
|
|
115
|
+
// deploy interpolates the written file again, so every dollar is escaped once more to survive that second pass.
|
|
116
|
+
return escapeDollar(run.stdout);
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
function releaseRecord(ctx, config, parts) {
|
package/sync/hygiene.mjs
CHANGED
|
@@ -126,7 +126,7 @@ export function judge(cwd, files) {
|
|
|
126
126
|
|
|
127
127
|
// The scripts/housekeeping/ledger-hygiene.mjs of the checkout under judgment: the root git names for `cwd`, which carries
|
|
128
128
|
// that script only when the repository IS a full StarCi runtime checkout (packages/hfs/sync/ sits 3 directories
|
|
129
|
-
// under such a root
|
|
129
|
+
// under such a root). A product repository — or a
|
|
130
130
|
// bare repo — has no such file, so the section is silently absent wherever this module happens to be installed.
|
|
131
131
|
const ledgerHygieneScript = cwd => {
|
|
132
132
|
try {
|
package/sync/index.mjs
CHANGED
|
@@ -176,7 +176,7 @@ export async function loadPresets(root) {
|
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
178
|
* The jest preset's Sonar exclusions as @starci/hfs ships them: `@starci/jest-preset/sonar-exclusions.cjs` (a require-free module),
|
|
179
|
-
*
|
|
179
|
+
* carried byte for byte in packages/hfs/runtime, so a fresh `starci app scaffold` (nothing installed
|
|
180
180
|
* yet) and an upgrade render the same list the app's installed preset answers. A missing copy is a refusal, never a render without it.
|
|
181
181
|
*/
|
|
182
182
|
const BUNDLED_SONAR_EXCLUSIONS = new URL('../runtime/packages/jest-preset/sonar-exclusions.cjs', import.meta.url);
|